gpt4 book ai didi

node.js - 如何使用 Nodejs 和 spawn 在 Windows 10 上以管理员身份运行一些 CMD 命令?

转载 作者:行者123 更新时间:2023-12-03 11:04:47 107 4
gpt4 key购买 nike

我在 Windows 10 上使用 Nodejs。每次打开应用程序时,我都想检查是否带有扩展名 ext 的文件与我的应用程序相关联。如果不是,我将需要在 cmd 上运行此命令以再次建立关联:

assoc .ext=CustomExt
ftype CustomExt=app.exe %1 %*
但是我需要管理员权限才能完成这项工作。
我已阅读 this thread Jeff M 说的正是我想要达到的目标,但没有人回答他:

From a usability perspective, the ideal would be that the user is prompted for elevated privileges only when he takes an action within my node program that actually requires those privileges. The second best option would be if the user was prompted for elevated privileges when they first start the node program. The least ideal is if the user isn't prompted at all, that it would be up to the user to always remember to start the program by right-click run as administrator. This is the least ideal because it puts to the burden on the user to remember to always start the program in a non-typical way.

So, to get back to my original question, right now if I try to spawn a child process where the program being spawned requires elevated privileges (example code in my original message), the current behavior is that the user is not prompted for those privileges, and instead the node program crashes with an error. How can I get my node program to request those privileges instead of just dying?


我的 nodejs 脚本:
const { spawn } = require('child_process');

const assoc = spawn( // how to run this as admin privileges?
'assoc', // command
['.ext=CustomExt'], // args
{'shell': true } // options: run this into the shell
);

assoc.stdout.on('data', (buffer) => {
var message = buffer.toString('utf8');
console.log(message);
});

assoc.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});

assoc.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
在 Nodejs 中创建扩展关联的任何其他方式也将受到赞赏。
2020 年 1 月 21 日更新
我相信 VSCode 可以做到这一点。所以我需要探索它的源代码来找到解决方案。现在在做其他项目,暂时没时间研究。当应该使用 root 权限保存文件时,会提示这样的消息,这正是我所需要的:
vscode prompt
2021 年 6 月 24 日更新
我找到了一个 useful thread in VSCode issues .使用 sudo-prompt 可能是解决方案。我还没试过,但是依赖还在 package.json ,所以看起来很有希望。

最佳答案

新的和改进的答案
有关背景,请参阅旧答案中的注释。我找到了一种无需允许在用户机器上运行脚本的方法:

import Shell from 'node-powershell'

/** Options to use when running an executable as admin */
interface RunAsAdminCommand {
/** Path to the executable to run */
path: string
/** Working dir to run the executable from */
workingDir?: string
}
/**
* Runs a PowerShell command or an executable as admin
*
* @param command If a string is provided, it will be used as a command to
* execute in an elevated PowerShell. If an object with `path` is provided,
* the executable will be started in Run As Admin mode
*
* If providing a string for elevated PowerShell, ensure the command is parsed
* by PowerShell correctly by using an interpolated string and wrap the
* command in double quotes.
*
* Example:
*
* ```
* `"Do-The-Thing -Param '${pathToFile}'"`
* ```
*/
const runAsAdmin = async (command: string | RunAsAdminCommand): Promise<string> => {
const usePowerShell = typeof command === 'string'
const shell = new Shell({})
await shell.addCommand('Start-Process')
if (usePowerShell) await shell.addArgument('PowerShell')
// Elevate the process
await shell.addArgument('-Verb')
await shell.addArgument('RunAs')
// Hide the window for cleaner UX
await shell.addArgument('-WindowStyle')
await shell.addArgument('Hidden')
// Propagate output from child process
await shell.addArgument('-PassThru')
// Wait for the child process to finish before exiting
if (usePowerShell) await shell.addArgument('-Wait')

if (usePowerShell) {
// Pass argument list to use in elevated PowerShell
await shell.addArgument('-ArgumentList')
await shell.addArgument(command as string)
} else {
// Point to executable to run
await shell.addArgument('-FilePath')
await shell.addArgument(`'${(command as RunAsAdminCommand).path}'`)

if ((command as RunAsAdminCommand).workingDir) {
// Point to working directory to run the executable from
await shell.addArgument('-WorkingDirectory')
await shell.addArgument(`'${(command as RunAsAdminCommand).workingDir}'`)
}
}

await shell.invoke()
return await shell.dispose()
}
用法示例:
const unzip = async (
zipPath: string,
destinationPath: string
): Promise<string> =>
await runAsAdmin(
`"Expand-Archive -Path '${zipPath}' -DestinationPath '${destinationPath}'"`
)
旧答案
我不是安全专家,如果你看到这里发生了一些愚蠢的事情,请挥舞红旗。
您可以使用 PowerShell 的 Start-Process 子进程中的 cmdlet。您需要包括 -Verb RunAs为了提高提示。
这将提示用户在调用 cmdlet 时允许该进程以管理员身份运行。您可以使用 node-powershell 来简化一些事情。如果需要。
这是带有适用标志的 cmdlet 示例(只需根据需要替换 [PATH_TO_EXECUTABLE][PATH_TO_DIR_TO_RUN_FROM]):
Start-Process -FilePath [PATH_TO_EXECUTABLE] -PassThru -Verb RunAs -WorkingDirectory [PATH_TO_DIR_TO_RUN_FROM]
警告
我们的应用程序使用 .ps1 执行此操作打包在 Electron 应用程序中的文件,而不是单行 PowerShell 脚本。在我们的案例中,这不是问题,因为该应用程序是一个内部工具,因此当我们指示他们设置适用的 PowerShell 权限以允许运行脚本时,最终用户信任他们。如果您不能依赖 .ps1您的里程可能会有所不同。如果您可以选择此选项, Set-ExecutionPolicy 是你的 friend 。我们让用户在安装应用程序后做这样的事情:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
dir "$env:USERPROFILE\AppData\Local\Programs\path\to\our\scripts" | Unblock-File
哪里 $env:USERPROFILE\AppData\Local\Programs\path\to\our\scripts指向 .ps1的目录与应用程序一起打包的文件。通过这种方式,用户只允许 PowerShell 运行我们提供给他们的脚本,而不是做一些愚蠢的事情,例如让它们允许所有 PowerShell 脚本无论来源如何都可以运行。 -ExecutionPolicy RemoteSigned是这里的秘诀;它说“只执行来自可信来源的下载脚本”。 (您也可以使用 -ExecutionPolicy AllSigned 来限制更多。)下一行,您将脚本目录中的所有文件通过管道传输到 Unblock-File。说“此目录中的脚本来自受信任的来源。”

关于node.js - 如何使用 Nodejs 和 spawn 在 Windows 10 上以管理员身份运行一些 CMD 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53090131/

107 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com