簡體   English   中英

更改調用過程的環境變量

[英]Changing environment variables of the calling process

這個看似微不足道,但是答案已經使我隱瞞了幾天。

我有一個Windows批處理文件,該文件調用C#程序執行無法在批處理文件中完成的額外驗證。 驗證完成后,我需要將狀態和字符串返回給調用shell。

現在返回值是微不足道的,並且我的C#控制台應用程序只需設置一個返回值(如果願意,可以設置退出代碼)。 而且我認為這串菜也將是小菜一碟。 我試圖使用以下命令定義一個新的shell變量:

Environment.SetEnvironmentVariable("ERR", "Some text");

該調用應該(並且確實)在當前進程中定義一個shell變量-這就是創建變量的C#進程。 一旦C#應用程序終止並且創建C#應用程序的外殼對該變量一無所知,該值就會丟失。 因此...沒有特殊用途的調用...完全...除非除非我從C3應用程序創建了一個子進程,否則它可能會繼承我的變量。

SetEnvironmentVariable調用的EnvironmentVariableTarget.Machine和EnvironmentVariableTarget.User目標也不能解決問題,因為只有新創建的進程才能從注冊表中獲取這些新值。

因此,我能想到的唯一可行的解​​決方案是:

  • 寫入標准輸出
  • 寫入文件
  • 將額外的含義編碼為返回值

前兩個有點難看,最后一個有其局限性和問題。

還有其他想法(如何在父進程中設置shell變量)? 也許這樣的shell變量修改是出於安全考慮(請考慮PATH)...

感謝您的時間。

我遇到了與Ryan相同的問題,作為解決方法,我唯一想到的是寫出一個錯誤的批處理來設置變量並從該批處理中調用它。

ConsoleApplication1.exe:

'put some sensible code here
'put result in variable myResult
Dim myResult As String = Guid.NewGuid().ToString("D").ToUpperInvariant()
Console.WriteLine("Normal output from the consonle app")
Console.Error.WriteLine("@ECHO OFF")
Console.Error.WriteLine("SET zzzResult={0}", myResult)

Test.cmd(調用批處理):

@ECHO OFF
:Jump to folder of batch file
PUSHD %~d0%~p0

:Define a temp file
SET zzzTempFile=%TEMP%\TMP%Random%.CMD

:Call .NET console app
ConsoleApplication1.exe 2>%zzzTempFile%

:Call the generated batch file
CALL %zzzTempFile%

:Clean up temp file
DEL %zzzTempFile%

:Clean up variable
SET zzzTempFile=

:Do something with the result
ECHO Yeah, we finally got it!
ECHO:
ECHO The value is "%zzzResult%".
ECHO:

:Clean up result variable
SET zzzResult=

:Go back to original folder
POPD

這應該夠了吧。 是的,我的確知道這是一篇老文章,而Ryan現在正在解決其他問題,但是可能還有其他人存在相同的問題...

您要問的是能夠任意寫入正在運行的進程的內存空間。 出於充分的原因,沒有SeDebugPrivilege是不可能的。

您列出的三種解決方案中的任何一種都可以使用。 Stdout是與批處理腳本進行通信的標准方法。

順便說一句,您正在編寫Windows批處理文件。 我很確定這艘船已經“有點丑”航行了。

如果要在批處理中將某些輸出的值放入變量中,則可以使用以下構造:

FOR /F "usebackq tokens=4 delims=\[\] " %i IN (`ver`) DO set VERSION=%i
ECHO %VERSION%

我的操作系統上的輸出:

6.1.7601

'usebackq'意味着我們正在使用反引號,從而可以在命令中使用雙引號將文件集使用。 您可能不需要這個。 “令牌”是指要選擇的結果字符串數組中的索引(可以是范圍MN)。 如果您需要跳過行,請使用“ skip = X”)。 'delims'是要使用的字符串分隔符(如.Net中的string-Split())。

您將放置控制台應用程序而不是“ ver”,並修改定界符和令牌以匹配您的特定輸出。 如果要填充的變量更多,則需要使if稍微復雜一些,但這應該是一個好的開始。

在我自己也對此有所迷戀之后,我想到了這種方法。 我所做的是使用Process類運行bat文件,即

// Spawn your process as you normally would... but also have it dump the environment varaibles
Process process = new Process();
process.StartInfo.FileName = mybatfile.bat;
process.StartInfo.Arguments = @"&&set>>envirodump.txt";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = false;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

// Read the environment variable lines into a string array
string[] envirolines = File.ReadAllLines("envirodump.txt");
File.Delete("envirodump.txt");

// Now simply set the environment variables in the parent process
foreach(string line in a)
{
    string var = line.Split('=')[0];
    string val = line.Split('=')[1];
    Environment.SetEnvironmentVariable(var, val);
} 

這似乎對我有用。 這不是最干凈的方法,但可以綁定使用。 :)

我的BAT有點生銹,但是我認為可以從外部運行的進程(可能通過%ERRORLEVEL%檢索“退出”代碼。 如果是這種情況,請確保通過退出程序

Environment.Exit(123); // where 123 = error code

您無法添加任何消息,因此必須在.bat文件中進行添加。

如果不是這種情況,則stdout可能是最好的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM