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

У меня есть рабочий сценарий 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-адрес

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

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 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. Я просто не могу заставить его работать.

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

3 ответы

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

$target = '$server'

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

$target = "$server"

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

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

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

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

$target = '$server'

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

$target = "$server"

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

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

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

Обновление: см. Нижнюю часть для теории.

Тестирование кода 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 - успех, в противном случае возвращается стандартная ошибка API Windows) ,

Обновить:

Под экземпляром 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. This question might help: Reading 64bit Registry from a 32bit application

0
добавлено
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

PowerShellRus - о Powershell (и не только) на русском
PowerShellRus - о Powershell (и не только) на русском
418 участник(ов)

О Powershell на русском

PowerShell Pro
PowerShell Pro
75 участник(ов)

Чат, посвящённый языку PowerShell Правила чата: нет оффтопу, спаму, оскорблениям. Будьте вежливы к коллегам. Приятного общения! Книги можно найти по тегу #books