windows 执行应用程序作为上下文菜单操作与参数

hgncfbus  于 2023-03-31  发布在  Windows
关注(0)|答案(2)|浏览(156)

bounty将于明天到期。此问题的答案可获得+50声望奖励。Eric Ballard正在寻找此问题的更详细答案

我想以与在Windows 10上使用特定上下文菜单操作时相同的方式编程启动应用程序。

上下文菜单是由应用程序Proxifier提供的,所以从我的研究中,我能够在我的注册表中找到这个,我相信这是相关的上下文菜单条目。

但是,只有一个可见参数,它似乎是初始化Proxifier设置所请求的用户配置文件的路径。

尝试了几种不同的组合,并不能真正找出任何东西在那里......所以我想到的另一件事是检查窗口消息发送到Proxifier时,点击上下文菜单,与间谍++。
我已经做了,我只是不能似乎破译wParam或lParam或什么信息,我会发送,以选择正确的子菜单的行动。

任何帮助在这里将非常感激,谢谢!

xt0899hw

xt0899hw1#

虽然这不是一个完整的答案,但它可能会指导你。
代理程序通过dll实现Shell扩展。
您可以在C:\Windows\System32\ProxifierShellExt.dll中找到它
由于这些是作为Context Menu Handler实现的
总之,您需要以与shell相同的方式托管IContextMenu接口。
如果您熟悉COM接口和Windows API,您可以给予一下。
This回答中有更详细的描述。
还有一个系列从可怕的“旧的新的东西”博客,但链接(发现在该答案)不工作了。
我希望这有帮助!

jm81lzqq

jm81lzqq2#

我无法弄清楚如何通过访问上下文菜单来让它工作,我知道这在技术上是你的问题。然而,我相信我有一个变通办法,希望能对你有用。
此解决方法涉及复制代理程序配置文件(这只是一个xml格式的文件),并创建一个新的配置文件。在新的配置文件,我们创建一个新的规则与您指定的应用程序和所需的行动(直接,阻止,代理)并将其插入到规则列表的顶部,以便首先执行规则。然后启动应用程序。脚本将等待应用程序关闭,然后重新启动选择旧配置文件。
例如,运行脚本以阻止应用程序将是这样的:

.\proxifier.ps1 -Block -filePath "C:\Program Files\VideoLAN\VLC\vlc.exe"
# the output
Block C:\Program Files\VideoLAN\VLC\vlc.exe
Load temp profile    
# will wait until app is closed
Reload original profile # once you close the app

应用程序将添加到规则列表的顶部。

在proxifier日志窗口中,您将看到proxifier加载新配置文件,然后在应用程序关闭时重新加载旧配置文件。

[03.30 11:09:20] Profile test-temp loaded.
[03.30 11:09:32] Profile test loaded.

--
该脚本具有以下规则选项,这些选项是代理程序中的规则操作选项(阻止、直接、代理):

.\proxifier.ps1 -Block -filePath "C:\Program Files\VideoLAN\VLC\vlc.exe"
 .\proxifier.ps1 -Direct -filePath "C:\Program Files\VideoLAN\VLC\vlc.exe"
 .\proxifier.ps1 -Proxy -proxyId yourproxyID -filePath "C:\Program Files\VideoLAN\VLC\vlc.exe"

Proxifier保存您的代理列表,并为每个代理都有一个id。因此,当使用proxy参数时,您需要所需代理的id号(例如100,101)。要运行列表:

.\proxifier.ps1 -getProxyID
 
 GetID

id      : 100
type    : HTTPS
Options : 48
Port    : 8080
Address : 127.0.0.1

id      : 101
type    : SOCKS5
Options : 48
Port    : 8080
Address : 10.1.0.1

profilePathsavePath更改为您所需的位置。我已经测试过了,它确实成功地为所有操作设置了规则。

# add error handling for incorrect file paths
param(
    [parameter(Mandatory=$false,Position=0,ParameterSetName="Block")]    
    [switch]$Block,
    [parameter(Mandatory=$false,Position=0,ParameterSetName="Direct")]
    [switch]$Direct,
    [parameter(Mandatory=$false,ParameterSetName="ProxyAction",Position=0)]
    [switch]$Proxy,
    [parameter(Mandatory=$true,ParameterSetName="ProxyAction")]
    [string]$proxyId,
    [parameter(Mandatory=$true,Position=1,ParameterSetName="Direct")]
    [parameter(Mandatory=$true,Position=1,ParameterSetName="Block")]
    [parameter(Mandatory=$true,Position=1,ParameterSetName="ProxyAction")]
    [string]$filePath,
    [parameter(Mandatory=$false,ParameterSetName="proxyID")]
    [switch]$getProxyID

)

#path to the proxifer profile you want to copy (change as desired)
$profilePath = "C:\Users\userName\AppData\Roaming\Proxifier4\Profiles\fielName.ppx"
#path to existing proxifier exe (change as desired)
$proxifierPath = "C:\Program Files (x86)\Proxifier\Proxifier.exe"
#save path for temp proxifier profile (change as desired)
$savePath = "C:\Users\userName\AppData\Roaming\Proxifier4\Profiles\fileName-temp.ppx"

if ($getProxyID){
Write-host "GetID"
[xml]$xmlProxyID = Get-Content -Path $profilePath
Write-Output $xmlProxyID.ProxifierProfile.ProxyList.Proxy 
}
else{
    if ($block){
        $action = "Block" 
    }
    elseif ($direct) {
        $action = "Direct" 
    }
    elseif ($Proxy){
        $action = "Proxy" 
    }
    $ruleName = "My Name" > $null

    Write-Host $action, $filePath
    if (!($filePath.Contains("`""))){
        $filePath = '"{0}"' -f $filePath
    }
# create new element for the rule and set action
[xml]$xml = Get-Content -Path $profilePath
$newElement = $xml.CreateElement("Rule")
$newElement.SetAttribute("enabled","true") 
$childAction = $xml.CreateElement("Action") 
$childAction.SetAttribute("type",$action) 

# set proxy setting if using
if ($proxy){
    $childAction.InnerText = $proxyId 
}

# set application path
$childApplication = $xml.CreateElement("Applications")
$childApplication.InnerText =  $filepath

# $childTargets = $xml.CreateElement("Targets")()
# $childTargets.InnerText = "Any"

# rule name
$childName = $xml.CreateElement("Name")
$childName.InnerText =  $ruleName 

# appened items to element
$newElement.AppendChild($childAction) | Out-Null
$newElement.AppendChild($childApplication) | Out-Null
# $newElement.AppendChild($childTargets)
$newElement.AppendChild($childName) | Out-Null

# insert new element to top of rule list
$topRule = $xml.ProxifierProfile.RuleList.Rule[0] 
$parent = $topRule.ParentNode 
$parent.InsertBefore($newElement,$topRule) | Out-Null
$xml.Save($savePath) | Out-Null

Write-Output "Load temp profile"
Start-Process -FilePath $proxifierPath -ArgumentList $savePath,"silent-load"

# start specified program
$proc = Start-Process -FilePath $filePath -PassThru

# wait until program closes
while (!($proc.HasExited)) {
    Start-Sleep -Seconds 2
    
}

# re-load original profile
Write-Output "Reload original profile"
Start-Process -FilePath $proxifierPath -ArgumentList $profilePath,"silent-load"


}
这种方式不适用于proxifier。但可能适用于某些用例,例如我在这里使用7-zip的示例。因此我将离开这一部分。

访问文件上下文菜单中的某些项似乎非常困难(甚至可能是不可能的)在powershell中。我目前无法安装Proxifier,但我一直在用7-zip测试。我发现this blog post,它详细说明了如何在powershell中访问文件的上下文菜单项。这个问题,这也是在帖子中提到的是,有些项目只是不能很容易地访问(与子菜单的项目似乎不显示与此方法)。
使用post中的代码的示例输出如下:

$o = New-Object -com Shell.APplication
$folder = $o.NameSpace("C:\Users\myuser\Downloads\")
$file = $folder.ParseName("test.zip")

# list file's verbs (context menu items)
$file.Verbs()
# the output
Application Parent Name
----------- ------ ----
                   &Open
                   &test

                   Edit with &Notepad++
                   Share

                   Scan with Sophos Endpoint
                   Restore previous &versions

                   Cu&t
                   &Copy
                   Create &shortcut
                   &Delete
                   Rena&me
                   P&roperties

你可以看到相同文件的上下文菜单截图的输出的不同之处,你会看到“7-zip”选项丢失。这很可能也是Proxifier的情况:

所以,我的解决办法,虽然不是很优雅,是创建一个new context menu item(链接来自@mklement0对您的帖子的评论)。下面将创建一个新的上下文菜单项,名为customCommand。它使用您提到的类似格式的命令,但使用7-zip C:\Program Files\7-Zip\7zFM.exe "%1"打开文件。

New-Item -Path  Registry::HKEY_CLASSES_ROOT\*\shell\customCommand
New-Item -Path  Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command
New-ItemProperty -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command -name "(default)" -PropertyType String -value "C:\Program Files\7-Zip\7zFM.exe `"%1`""

运行上面的命令将创建以下注册表项:

可以看到新增了快捷菜单项customCommand,所有文件都会新增:

重新运行上面的$file.verbs()命令,我们可以看到我们的新条目现在已经列出(部分输出):

Application Parent Name
----------- ------ ----
                   &Open
                   &customCommand # our newly added item
                   &testing

现在我们可以通过运行以下命令来访问该项目:

$file.InvokeVerb("customCommand")

现在把所有这些放在一起,我们可以:

  • 通过添加注册表项创建上下文菜单项
  • 运行命令来访问和调用文件的上下文菜单项
  • 删除注册表项以清理备份上下文菜单

代码:

#change the folder path and file name
$folderPath = "C:\Users\somepath\Downloads\"
$fileName = "somefile.exe"
#I do not have Proxifier installed but looks like it is similar to the 7-zip command. (copied from your screenshot)
$theCommand = "C:\Program Files (x86)\Proxifier\Proxifier `"%1`""

# example tested working with 7-zip
#$theCommand = "C:\Program Files\7-Zip\7zFM.exe `"%1`""

if ((Test-Path -LiteralPath $folderPath) -AND (Test-Path -LiteralPath ($folderPath + $fileName))){
if (!(Test-Path -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand)){
    # create registry entries for the contex menu item
    Write-Host "Creating Registery Entry"
    New-Item -Path  Registry::HKEY_CLASSES_ROOT\*\shell\customCommand | Out-Null
    New-Item -Path  Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command | Out-Null
    New-ItemProperty -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command -name "(default)" -PropertyType String -value $theCommand  | Out-Null
}

# access and invoke the context menu item
Write-Host "Opening file with command"
$o = New-Object -com Shell.APplication
$folder = $o.NameSpace($folderPath)
$file = $folder.ParseName($fileName)
$file.InvokeVerb("customCommand") 


    if ((Test-Path -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command)){
        # remove the context menu item
        Write-Host "Removing Registry Entries"
        Remove-Item -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand\command | Out-Null
        Remove-Item -LiteralPath Registry::HKEY_CLASSES_ROOT\*\shell\customCommand | Out-Null
    }
}
else{
    Write-Host "Path doesn't exist. Registry entries not created"
}

命令行上的输出将如下(程序应启动):

理论上,这应该可以按照你想要的方式打开Proxifier。如果其他程序遵循与7-zip相同的格式,它也应该以类似的方式与其他程序一起工作。

相关问题