[英]Calling WNetAddConnection2 from PowerShell
I am trying to directly call some Win32 API's from a PowerShell script. 我试图从PowerShell脚本直接调用一些Win32 API。 I managed to make WNetAddConnection work with the code below: 我设法使WNetAddConnection使用以下代码:
$cp = New-Object Microsoft.CSharp.CSharpCodeProvider
$cpar = New-Object System.CodeDom.Compiler.CompilerParameters
$Code = @"
using System;
using System.Runtime.InteropServices;
namespace Win32Api
{
public class Net
{
[DllImport("mpr.dll", EntryPoint = "WNetAddConnection")]
public static extern uint Map(string lpRemoteName, string lpPassword, string lpLocalName);
[DllImport("mpr.dll", EntryPoint = "WNetCancelConnection")]
public static extern uint Delete(string lpName, byte fForce);
}
}
"@
$cp.CompileAssemblyFromSource($cpar, $code)
[Win32Api.Net]::Map("\\REMKOLAPTOP\C$", $null, "W:")
Now I would like to do the same WNetAddConnection2 , although I found the proper declarations for C# I am unsure how to declare this for usage in PowerShell. 现在我想做同样的WNetAddConnection2 ,虽然我发现C#的正确声明我不确定如何在PowerShell中声明这个用法。 So my questions is: what is the proper "translation" and an example of calling the API would be great. 所以我的问题是:什么是正确的“翻译”,调用API的例子会很棒。
Please note that I do not want to use non api methods like the one below: 请注意,我不想使用如下所示的非api方法:
$net = $(New-Object -Com WScript.Network)
$net.MapNetworkDrive("u:", "\\computer\share")
I was able to get the following code working on PowerShell 2.0. 我能够在PowerShell 2.0上获得以下代码。 Note that I also use one PSCX ( http://pscx.codeplex.com ) function that just converts a Windows error code into a message. 请注意,我还使用一个PSCX( http://pscx.codeplex.com )函数,只将Windows错误代码转换为消息。 I also setup the options to do an interactive prompt for username and password. 我还设置了用于对用户名和密码进行交互式提示的选项。 Commented out script is included that shows how you could do the same using PowerShell's Get-Credential cmdlet. 包含注释掉的脚本,显示了如何使用PowerShell的Get-Credential cmdlet执行相同操作。
BTW if you supply the username/password via variables to the function be sure to get the order right, it is password followed by username. 顺便说一句,如果您通过变量向该函数提供用户名/密码,请确保订单正确,密码后跟用户名。 That bit me for 10 minutes until I finally figured out I had the order wrong. 那点我10分钟,直到我终于弄明白我的订单错了。 Doh! 卫生署! One other tidbit, for interop help like this be sure to checkout http://www.pinvoke.net . 另外一个小问题,对于像这样的互操作帮助一定要结账http://www.pinvoke.net 。 Anyway, hope this helps. 无论如何,希望这会有所帮助。
$WNetAddConnection2WrapperSource = @'
using System;
using System.Runtime.InteropServices;
namespace Win32Api {
public enum ResourceScope {
RESOURCE_CONNECTED = 1,
RESOURCE_GLOBALNET,
RESOURCE_REMEMBERED,
RESOURCE_RECENT,
RESOURCE_CONTEXT
};
public enum ResourceType {
RESOURCETYPE_ANY,
RESOURCETYPE_DISK,
RESOURCETYPE_PRINT,
RESOURCETYPE_RESERVED = 8
};
[Flags]
public enum ResourceUsage {
RESOURCEUSAGE_CONNECTABLE = 0x00000001,
RESOURCEUSAGE_CONTAINER = 0x00000002,
RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
RESOURCEUSAGE_SIBLING = 0x00000008,
RESOURCEUSAGE_ATTACHED = 0x00000010,
RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE |
RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
};
public enum ResourceDisplayType {
RESOURCEDISPLAYTYPE_GENERIC,
RESOURCEDISPLAYTYPE_DOMAIN,
RESOURCEDISPLAYTYPE_SERVER,
RESOURCEDISPLAYTYPE_SHARE,
RESOURCEDISPLAYTYPE_FILE,
RESOURCEDISPLAYTYPE_GROUP,
RESOURCEDISPLAYTYPE_NETWORK,
RESOURCEDISPLAYTYPE_ROOT,
RESOURCEDISPLAYTYPE_SHAREADMIN,
RESOURCEDISPLAYTYPE_DIRECTORY,
RESOURCEDISPLAYTYPE_TREE,
RESOURCEDISPLAYTYPE_NDSCONTAINER
};
[StructLayout(LayoutKind.Sequential)]
public class NetResource {
public ResourceScope Scope;
public ResourceType Type;
public ResourceDisplayType DisplayType;
public ResourceUsage Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
};
[Flags]
public enum AddConnectionOptions {
CONNECT_UPDATE_PROFILE = 0x00000001,
CONNECT_UPDATE_RECENT = 0x00000002,
CONNECT_TEMPORARY = 0x00000004,
CONNECT_INTERACTIVE = 0x00000008,
CONNECT_PROMPT = 0x00000010,
CONNECT_NEED_DRIVE = 0x00000020,
CONNECT_REFCOUNT = 0x00000040,
CONNECT_REDIRECT = 0x00000080,
CONNECT_LOCALDRIVE = 0x00000100,
CONNECT_CURRENT_MEDIA = 0x00000200,
CONNECT_DEFERRED = 0x00000400,
CONNECT_RESERVED = unchecked((int)0xFF000000),
CONNECT_COMMANDLINE = 0x00000800,
CONNECT_CMD_SAVECRED = 0x00001000,
CONNECT_CRED_RESET = 0x00002000
}
public static class NativeMethods {
[DllImport("mpr.dll", EntryPoint="WNetAddConnection2")]
public static extern int WNetAddConnection2(
NetResource netResource, string password,
string username, AddConnectionOptions options);
}
}
'@
Add-Type -TypeDefinition $WNetAddConnection2WrapperSource
$netResource = new-object Win32Api.NetResource
$netResource.Type = [Win32Api.ResourceType]::RESOURCETYPE_DISK
$netResource.LocalName = 'P:'
$netResource.RemoteName = '\\AnotherPC\C'
# Get username and password
#$cred = Get-Credential
#$username = $cred.UserName
#$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.Password)
#$password = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
#[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$opts = [Win32Api.AddConnectionOptions]::CONNECT_INTERACTIVE -bor
[Win32Api.AddConnectionOptions]::CONNECT_PROMPT -bor
[Win32Api.AddConnectionOptions]::CONNECT_UPDATE_PROFILE
$res = [Win32Api.NativeMethods]::WNetAddConnection2($netResource, 0, 0, $opts)
if ($res -ne 0) {
# This function comes with PSCX http://pscx.codeplex.com
Get-ExceptionForWin32 $res
throw "Failed to connect"
}
# Display results
net use
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.