从 Powershell 调用的 DLL 使用相对于 Powershell 安装目录的路径。如何将其设置为其他内容?
Posted
技术标签:
【中文标题】从 Powershell 调用的 DLL 使用相对于 Powershell 安装目录的路径。如何将其设置为其他内容?【英文标题】:DLL invoked from Powershell uses paths relative to Powershell install directory. How can I set it to something else? 【发布时间】:2017-07-03 21:29:36 【问题描述】:我有一个带有静态方法的 DLL,我从 Powershell 脚本调用它。
此静态方法使用与网站共享的 log4net 配置执行一些任务并记录结果 - log4net 配置基于 web.config 文件,Powershell 脚本使用此 web.config 文件,如下所示:
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $webconfigpath)
这很好用,log4net 成功获取配置,如下所示:
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="App_Data/log/process.log" />
<appendToFile value="true" />
[..]
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
问题在于,当它尝试使用相对路径 App_Data/log/process.log 时,它使用的是 C:\Windows\System32\WindowsPowerShell\v1 的基本路径。 0\.
如何将此基本路径设置为我选择的路径?
我不想在 web.config 中使用绝对路径,因为此代码需要在具有不同文件系统设置的多个不同环境中工作。
我曾尝试使用Set-Location
cmdlet,但这不起作用。我也尝试过设置[Environment]::CurrentDirectory
,但这似乎也不起作用。不管我怎么改,DLL代码都会使用Powershell的安装目录作为它的工作目录。
我的 Powershell 脚本如下所示:
$webroot = "$PSScriptRoot\..\webdir";
$webconfig = "$webroot\web.config";
# Neither of these seem to set the working directory for the DLL
#Set-Location $webroot
#[Environment]::CurrentDirectory = $webroot
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Configuration")
[void][System.Reflection.Assembly]::LoadFrom("$webroot\bin\Custom.Code.dll")
if (!(Test-Path $webconfig))
Throw "Aborting, could not locate web.config at $webconfig";
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $webconfig)
$result = [Custom.Code.Task]::Execute()
Write-Host $result
如何为 DLL 代码提供路径以用作相对基础?
【问题讨论】:
嗨@r41n,我可以加载我的DLL并在其中调用代码,这不是问题。问题是 log4net 的配置使用日志文件的相对路径,但它基于 Powershell 安装目录中的相对路径,而不是运行脚本的位置。 对不起,看来完全错了。删除了我没用的 cmets。 如果我正确理解了这个问题,我会说这是预期的行为。 DLL 的代码在执行调用处理的目录中执行。使用 cd (aka.Set-Location) 不会更改 powershell.exe 的启动目录,只有 dir powershell 正在运行。您可以尝试运行 Powershell 并使用以下示例行启动另一个 Powershell 实例Start-Process -FilePath powershell.exe -WorkingDirectory c:\temp
和将“C:\temp”替换为所需的目录,在这种情况下,脚本可能能够找到您的配置文件。
我能想到的唯一其他选择是更改 DLL 并使其接受包含配置文件目录的参数。
实际上上述 Start-Process cmdlet 语法会引发错误。以下应该可以解决问题:`Start-Process powershell.exe -Verb RunAs -WorkingDirectory C:`(它需要提升的权限)。我仍然认为最好的办法是调整 DLL 的代码以接受参数。
【参考方案1】:
我们为不同的环境解决这个问题的方法是使用环境变量。每个开发人员对他们想要记录内容的位置都有自己的想法,prod 环境有另一组位置。
在您的具体情况下,您可以在 PowerShell 中使用以下环境变量:
$env:MyLogs = "$webroot\"
# or [Environment]::SetEnvironmentVariable("MyLogs","$webroot\")
然后将您的记录器设置为这样 (based on the log4net documentation):
<file value="$MyLogsApp_Data/log/process.log" />
如果您不仅有需要该变量的 log4net,那么他们应该有自己的获取环境变量的方法。
【讨论】:
以上是关于从 Powershell 调用的 DLL 使用相对于 Powershell 安装目录的路径。如何将其设置为其他内容?的主要内容,如果未能解决你的问题,请参考以下文章
从 PowerShell 调用时无法在 dll 中转换透明代理,但在 C# 控制台应用程序中成功
使用powershell通过配置文件config调用wcf(含用户名密码认证)