WedX - журнал о программировании и компьютерных науках

Скрипт работает в Powershell, но ошибка при запуске в С#

У меня есть рабочий скрипт powershell для получения ключа продукта Windows с машины в нашей сети. Скрипт хорошо работает в командной строке powershell, но возвращает ошибку, когда я пытаюсь запустить его из C#. Мне нужно, чтобы это работало, чтобы наметить лицензии в нашей корпорации.

Код PowerShell:

function Get-WindowsKey {
$target = '$server'
$hklm = 2147483650
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"
$regValue = "DigitalProductId4"
$productKey = $null
$win32os = $null
$wmi = [WMIClass]"\\$target\root\default:stdRegProv"
$data = $wmi.GetBinaryValue($hklm,$regPath,$regValue)
$binArray = ($data.uValue)[52..66]
$charsArray = "B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9"
For ($i = 24; $i -ge 0; $i--) {
    $k = 0
    For ($j = 14; $j -ge 0; $j--) {
        $k = $k * 256 -bxor $binArray[$j]
        $binArray[$j] = [math]::truncate($k / 24)
        $k = $k % 24
    }
    $productKey = $charsArray[$k] + $productKey
    If (($i % 5 -eq 0) -and ($i -ne 0)) {
        $productKey = "-" + $productKey
    }
}
$productkey
}
Get-WindowsKey | Format-Table -AutoSize

Просто замените $server на . или ваш IP

Код С#, который запускает скрипт:

private void RunWindowsKeyScript(string IP)
{
    try
    {
        Assembly keyAssembly = this.GetType().Assembly;
        ResourceManager keyResMan = new ResourceManager("LanMap.Resources.PS script", keyAssembly);
        string keyScript = keyResMan.GetString("WindowsKey");
        keyScript = keyScript.Replace("$server", IP);
        Runspace keyRunspace = RunspaceFactory.CreateRunspace();
        keyRunspace.Open();
        Pipeline keyPipeline = keyRunspace.CreatePipeline();
        keyPipeline.Commands.AddScript(keyScript);
        keyPipeline.Commands.Add("Out-String");
        Collection<psobject> keyResults = keyPipeline.Invoke();
        keyRunspace.Close();
        StringBuilder keyStringBuilder = new StringBuilder();
        foreach (PSObject obj in keyResults)
        {
            keyStringBuilder.AppendLine(obj.ToString());
        }
    }
    catch (Exception ex)
    {
        string s = "";
        s += " ";
    }
}

Пожалуйста, помоги, если можешь. Я уже знаю, что ошибка в том, что в C# GetBinaryValue возвращает null. Я просто не могу заставить его работать.

29.01.2013

  • Вы уже проверили следующую страницу? или, может быть, эта страница? 29.01.2013
  • После исправления некоторых проблем компиляции и использования другого метода получения ResourceManager я обнаружил, что ваш скрипт/код прекрасно работает на моей машине. Какую ошибку вы видите? 29.01.2013
  • да. Пробовал и это тоже безрезультатно. 29.01.2013
  • Для меня $wmi.GetBinaryValue($hklm,$regPath,$regValue) возвращает ноль, и в результате я получаю исключение Не могу вставить в нулевой массив или результат BBBBB-BBBBB-...BB 29.01.2013
  • 1. В каком состоянии конвейер keyPipeline после Invoke? (В частности, keyPipeline.PipelineStateInfo Failed или Stopped?). 2. Что содержит keyStringBuilder в конце блока try? 29.01.2013
  • Прямо сейчас, сразу после Invoke, возникает ошибка (переход к Catch). Невозможно индексировать нулевой массив. 29.01.2013
  • Если вы скажете, что у вас это работает нормально, не могли бы вы помочь мне найти способ узнать, что мешает ему работать. Как мне грустно, в командной строке powershell она работает, но не на С#. Есть ли что-нибудь, что может заблокировать запрос реестра в моем случае (c # powershell). Я подозреваю, что это могут быть какие-то сетевые настройки. 29.01.2013
  • В какой строке возникает исключение? (Он должен содержать сведения о том, какой оператор и где в этом операторе: посмотрите на другие свойства исключения.) 29.01.2013
  • @Richard: 1. Keypipeline.PipelineStateInfo.State = Failed 2. строка результата равна нулю. 29.01.2013
  • Это имеет смысл, если выдается исключение: поместите соответствующую запись в журнал исключения, чтобы сообщить вам, где в сценарии PSH возникает ошибка. 30.01.2013
  • Как я уже сказал в начальной отправке, ошибка генерируется GetBinaryValue(). Это значение null при работе на С#, и я не знаю, почему. 30.01.2013
  • Извините, что пропустил это: пожалуйста, обновите вопрос, указав эти детали, чтобы информация была представлена ​​связно. Следующий шаг: забудьте об удаленном взаимодействии на данный момент: используйте Get-ItemProperty для прямого чтения реестра (т. е. в обход WMI). 30.01.2013
  • Важный вопрос: как вы запускаете код .NET? (например, консольное приложение из консоли PowerShell.) 30.01.2013

Ответы:


1

Я не уверен, как вы заставили это работать в форме сценария с этим:

$target = '$server'

Строки в одинарных кавычках не будут расширять переменные внутри них. Это должно работать нормально:

$target = "$server"

Обычно этого было бы достаточно $target = $server, но поскольку вы выполняете замену строки, лучше придерживаться двойных кавычек.

Другая возможность заключается в том, что ваш код C# работает как x86, и вы читаете реестр WOW64 вместо 64-разрядного реестра. Это может объяснить, почему вы видите разные результаты между запуском скрипта и запуском через приложение C#.

29.01.2013
  • Это не так, обратите внимание, что код C# заменяет строку на "$server" некоторым параметром функции C#. (Но я думаю, что основной причиной является некоторая переменная, унаследованная от сеанса PSH при использовании консоли, которая не будет присутствовать в C#.) 30.01.2013
  • Да, это немного странный код - замена строки. Похоже, было бы лучше просто сделать $server параметром функции и скрипта и передать его. 30.01.2013
  • Даже без замены, если весь текст вводится как строка со статическим IP-адресом, выдается ошибка. 30.01.2013

  • 2

    Обновление: см. Теорию внизу.

    Тестирование кода PowerShell из ISE: похоже, что GetBinaryValue не работает:

    $target = 'localhost'
    $hklm = 2147483650
    $regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"
    $regValue = "DigitalProductId4"
    $productKey = $null
    $win32os = $null
    $wmi = [WMIClass]"\\$target\root\default:stdRegProv"
    $data = $wmi.GetBinaryValue($hklm,$regPath,$regValue)
    
    if ($data -eq $null) { Write-DEbug "Data is NULL"; return "STOP 2" }
    
    write-debug '$Data'
    write-debug ("$($data): " + ($data | gm | out-string))
    write-debug ("$($data): " + ($data | fl * | out-string))
    
    if ($data.uValue -eq $null) { Write-Debug "Data.uValue is NULL"; return "STOP 3" }
    # rest cut for testing
    

    приводит к:

    DEBUG: $Data
    DEBUG: System.Management.ManagementBaseObject: 
    
       TypeName: System.Management.ManagementBaseObject#\__PARAMETERS
    
    Name             MemberType    Definition                      
    ----             ----------    ----------                      
    PSComputerName   AliasProperty PSComputerName = __SERVER       
    ReturnValue      Property      uint32 ReturnValue {get;set;}   
    uValue           Property      byte[] uValue {get;set;}        
    __CLASS          Property      string __CLASS {get;set;}       
    __DERIVATION     Property      string[] __DERIVATION {get;set;}
    __DYNASTY        Property      string __DYNASTY {get;set;}     
    __GENUS          Property      int __GENUS {get;set;}          
    __NAMESPACE      Property      string __NAMESPACE {get;set;}   
    __PATH           Property      string __PATH {get;set;}        
    __PROPERTY_COUNT Property      int __PROPERTY_COUNT {get;set;} 
    __RELPATH        Property      string __RELPATH {get;set;}     
    __SERVER         Property      string __SERVER {get;set;}      
    __SUPERCLASS     Property      string __SUPERCLASS {get;set;}  
    
    
    
    DEBUG: System.Management.ManagementBaseObject: 
    
    PSComputerName   : 
    __GENUS          : 2
    __CLASS          : __PARAMETERS
    __SUPERCLASS     : 
    __DYNASTY        : __PARAMETERS
    __RELPATH        : 
    __PROPERTY_COUNT : 2
    __DERIVATION     : {}
    __SERVER         : 
    __NAMESPACE      : 
    __PATH           : 
    ReturnValue      : 2
    uValue           : 
    Properties       : {ReturnValue, uValue}
    SystemProperties : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
    Qualifiers       : {}
    ClassPath        : __PARAMETERS
    Site             : 
    Container        : 
    
    
    
    
    DEBUG: Data.uValue is NULL
    STOP 3
    

    Этот ReturnValue: 2 соответствует ERROR_FILE_NOT_FOUND (при условии, что элемент ReturnValue отражает возвращаемое значение GetBinaryValue, где 0 означает успех, в противном случае возвращается стандартная ошибка Windows API).

    Обновлять:

    Под экземпляром ISE даже получить это:

    PS [32] C:\ #50> gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"
    gp : Cannot find path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey' because it does not exist.
    At line:1 char:1
    + gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (HKLM:\SOFTWARE\...faultProductKey:String) [Get-ItemProperty], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
     
    

    Но я вижу ключ... однако 64-битный экземпляр ISE работает.

    Ключ доступен (напрямую) только для 64-битных процессов, по умолчанию в последних версиях Visual Studio большинство приложений создаются как 32-битные (большинству приложений не требуется дополнительное адресное пространство), 32-битное приложение .NET загрузит 32-битное Сборки среды выполнения PowerShell.

    Вы пытались создать свое приложение для 64-битной версии?

    PS. Этот вопрос может помочь: Чтение 64-битного реестра из 32-битного приложения

    30.01.2013
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]