我试图内联的 C# 位于底部,但我的错误发生在第二个 DllImport,因为未加载 StringBuilder。我已经尝试了很多关于加载程序集、在 C# 中添加使用引用等的事情。这是一个例子。但是没有任何效果,我很确定我只是遗漏了一些对 C# 程序员来说非常明显的东西,而对我的大脑来说完全不明显。
$assemblies = ('mscorlib.dll')
$code = @'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static class PxTest
{
// Note
}
'@
Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -name Test -errorAction stop
我也试过
$assemblies = ('system.text')
然后尝试加载未找到的 system.text.dll。这就是将我发送到上面的 dll 的原因,我相信这是找到 StringBuilder 的地方。最终使用的 C# 代码
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static bool PinUnpinTaskbar(string filePath, bool pin)
{
if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Equals(localizedVerb))
{
verb.DoIt();
return true;
}
}
return false;
}
编辑:试图理解编辑。我得到了添加的标签,但用...相同的文本替换了一些正文?我不明白的。这至少是我所看到的。 StringBuilder 是 替换为 StringBuilder 是 等等,嗯?
最佳答案
这是因为StringBuilder
不是完全限定的和/或命名空间 System.Text
未使用
所以要么将参数更改为
System.Text.StringBuilder lpBuffer
或添加
UsingNamespace
Add-Type
的参数小命令Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -UsingNamespace 'System.Text' -name Test -errorAction stop
由于您的环境固定为 PoSh 2.0 和 Win7,我重写了代码以通过 PowerShell 处理动态内容(无论如何在这种情况下更惯用)并通过您提供的 C# 代码获取本地化动词,因此最终看起来像这样为您提供方便的PowerShell功能
PinUnpinTaskbar
$assemblies = ('mscorlib.dll')
$code = @'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static string GetLocalizedPinToStartVerb(bool pin)
{
int MAX_PATH = 255;
int actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
return szPinToStartLocalized.ToString();
}
'@
Add-Type -MemberDefinition $code `
-ReferencedAssemblies $assemblies `
-Namespace Px `
-UsingNamespace 'System.Text' `
-Name Helper `
-ErrorAction stop
function PinUnpinTaskbar([string]$FilePath, [boolean]$Pin) {
if (Test-Path $FilePath) {
$localizedVerb = [Px.Helper]::GetLocalizedPinToStartVerb($Pin)
$path = [IO.Path]::GetDirectoryName($FilePath)
$fileName = [IO.Path]::GetFileName($FilePath)
$shellAppType = [Type]::GetTypeFromProgID("Shell.Application")
$shellAppInst = [Activator]::CreateInstance($shellAppType)
$directory = $shellAppInst.NameSpace($path)
$link = $directory.ParseName($fileName)
$verbs = $link.Verbs()
for ($i = 0; $i -lt $verbs.Count; ++$i) {
$verb = $verbs.Item($i)
Write-Host $verb.Name
if ($verb.Name.Equals($localizedVerb)) {
$verb.DoIt()
return $true
}
}
return $false
}
else {
Write-Error "File '$FilePath' does not exist"
}
}
在普通 Win7 机器上运行的脚本
关于c# - PowerShell 中内联 C# 中的 ScriptBuilder(2.0 及更高版本),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38942498/