diff --git a/common/process.h b/common/process.h index 48b14a7..be09153 100644 --- a/common/process.h +++ b/common/process.h @@ -53,6 +53,10 @@ struct ProcessStartInfo { // Command line, UTF-8 encoded. std::string command; + // Full path to the process startup working directory. + // If empty, uses parent process working dir. + std::string startup_dir; + // If set, the process stdin is redirected to a pipe. // It not set, the input is connected to the stdin of the calling process. bool redirect_stdin = false; diff --git a/common/process_test.cc b/common/process_test.cc index ed4f151..0540515 100644 --- a/common/process_test.cc +++ b/common/process_test.cc @@ -342,5 +342,20 @@ TEST_F(ProcessTest, TerminateAlreadyExited) { EXPECT_OK(process->Terminate()); } +TEST_F(ProcessTest, StartupDir) { + ProcessStartInfo start_info; + start_info.command = "cmd /C cd"; + start_info.startup_dir = "C:\\"; + + std::string std_out; + start_info.stdout_handler = [&std_out](const char* data, size_t) { + std_out += data; + return absl::OkStatus(); + }; + + EXPECT_OK(process_factory_.Run(start_info)); + EXPECT_EQ(std_out, "C:\\\r\n"); +} + } // namespace } // namespace cdc_ft diff --git a/common/process_win.cc b/common/process_win.cc index 20447d6..080b041 100644 --- a/common/process_win.cc +++ b/common/process_win.cc @@ -719,6 +719,10 @@ absl::Status WinProcess::Start() { Util::GetLastWin32Error()); } + std::wstring startup_dir = Util::Utf8ToWideStr(start_info_.startup_dir); + const wchar_t* startup_dir_cstr = + !startup_dir.empty() ? startup_dir.c_str() : nullptr; + // Start the child process. success = CreateProcess(NULL, // No module name (use command line) command_cstr, @@ -727,8 +731,7 @@ absl::Status WinProcess::Start() { TRUE, // Inherit handles ToCreationFlags(start_info_.flags), NULL, // Use parent's environment block - NULL, // Use parent's starting directory - &si, &process_info_->pi); + startup_dir_cstr, &si, &process_info_->pi); if (!success) { return MakeStatus("CreateProcess() failed: %s", Util::GetLastWin32Error());