[英]Script running in Powershell but error when run in C#
I have a working powershell script to get the Windows product key from an machine in our network. 我有一个有效的Powershell脚本,可以从我们网络中的计算机上获取Windows产品密钥。 The script runs well in powershell comand line but returns error when I try to run it from C#.
该脚本在powershell comand行中运行良好,但是当我尝试从C#运行该脚本时返回错误。 I need this working to chart licenses in our corporation.
我需要这项工作来绘制我们公司的许可证表。
Powershell code: 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
Just replace $server with . 只需将$ server替换为即可。 or your IP
或您的IP
C# code that runs script: 运行脚本的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<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 += " ";
}
}
Please help if you can. 如果可以的话请帮忙。 I already know the error is that in C# GetBinaryValue returns null.
我已经知道错误是在C#中,GetBinaryValue返回null。 I just can not make it work.
我只是无法使其工作。
I'm not sure how you got this to work in script form with this: 我不确定您是如何通过以下方式以脚本形式工作的:
$target = '$server'
Single quoted strings will not expand variables inside them. 用单引号引起来的字符串不会在其中扩展变量。 This should work just fine:
这应该可以正常工作:
$target = "$server"
This would normally be sufficient $target = $server
but since you're doing a string replace, it is best to stick with the double quotes. 通常
$target = $server
就足够$target = $server
但是由于您正在执行字符串替换,因此最好坚持使用双引号。
Another possibility is that you're C# code is running as x86 and you're reading the WOW64 registry instead of the 64-bit registry. 另一种可能性是您正在将C#代码作为x86运行,并且正在读取WOW64注册表而不是64位注册表。 That might explain why you see different results between running the script and running via your C# app.
这也许可以解释为什么您在运行脚本和通过C#应用程序运行之间看到不同的结果。
Update: See bottom for theory. 更新:理论请参见底部。
Testing the PowerShell code from ISE: looks like GetBinaryValue
is failing: 从ISE测试PowerShell代码:看起来
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
results in: 结果是:
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
That ReturnValue: 2
corresponds to ERROR_FILE_NOT_FOUND (assuming the ReturnValue
member is reflecting the return value of GetBinaryValue
where 0 is success, otherwise standard Windows API error returns). 该
ReturnValue: 2
对应于ERROR_FILE_NOT_FOUND(假定ReturnValue
成员反映了GetBinaryValue
的返回值,其中0为成功,否则返回标准Windows API错误)。
Under by ISE instance even get this: 在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
But I can see the key... however a 64 bit instance of ISE and it works. 但是我可以看到密钥……但是ISE的64位实例可以正常工作。
The key is only available (directly) to 64bit processes, the default in recent Visual Studio versions is for most applications to be built as 32bit (most applications don't need the extra address space), a 32bit .NET application will load the 32bit PowerShell runtime assemblies. 该密钥仅(直接)适用于64位进程,最新的Visual Studio版本中的默认设置是,对于大多数应用程序,其构建为32位(大多数应用程序不需要额外的地址空间),一个32位.NET应用程序将加载32位PowerShell运行时程序集。
Have you tried building your application for 64bit? 您是否尝试过为64位构建应用程序?
PS. PS。 This question might help: Reading 64bit Registry from a 32bit application
该问题可能会有所帮助: 从32位应用程序读取64位注册表
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.