Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cmder for Windows - Add Bash, Powershell, mintty. #2942

Open
wants to merge 29 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9ce6911
add bash and powershell to Cmder for Windows
daxgames Nov 24, 2023
467d564
cleanup
daxgames Nov 24, 2023
3ff9737
Merge remote-tracking branch 'origin/development' into development
daxgames Nov 24, 2023
a7f19f5
cleanup
daxgames Nov 24, 2023
2beb27d
cleanup
daxgames Nov 24, 2023
0f6c91d
cleanup
daxgames Nov 24, 2023
7a385eb
cleanup
daxgames Nov 24, 2023
0a691cb
Merge remote-tracking branch 'upstream/development' into development
daxgames Nov 24, 2023
d8238b0
cleanup
daxgames Nov 24, 2023
4729203
add mintty
daxgames Nov 27, 2023
38a91de
cleanup
daxgames Nov 27, 2023
28e9018
make mintty /a work
daxgames Nov 27, 2023
c5579d2
Add Monokai, Default to One Half Dark
daxgames Jan 2, 2024
1ed3a36
Update windows_terminal_default_settings.json
daxgames Jan 2, 2024
5814792
Merge pull request #15 from daxgames/development-dax
daxgames Jan 2, 2024
c594642
update build workflow to upload cmder_win.zip
daxgames May 30, 2024
9463d4e
update build workflow to upload cmder_win*
daxgames May 30, 2024
167f57b
Merge branch 'upstream-development' into cmder4win
daxgames May 30, 2024
f38e0b3
sync
daxgames May 30, 2024
ffa37d4
sync fix launcher overwrite
daxgames Aug 22, 2024
980083f
Merge pull request #23 from daxgames/more_speed_2
daxgames Jan 5, 2025
6cf4a42
Merge pull request #24 from daxgames/fix_launcher_overwrite-2
daxgames Jan 5, 2025
bd3f132
Merge branch 'origin-development-dax' into cmder4win
daxgames Jan 5, 2025
0c2e5ce
CHANGELOG.md
daxgames Jan 6, 2025
b00dce8
Merge remote-tracking branch 'origin/cmder4win' into cmder4win
daxgames Jan 6, 2025
e0aa20a
CHANGELOG.md
daxgames Jan 6, 2025
d349f57
add executionpolicy bypass
daxgames Jan 6, 2025
8683dad
Remove /a switch and associated code.
daxgames Jan 6, 2025
c1bbc46
Merge branch 'upstream-development' into cmder4win
daxgames Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,27 @@ jobs:
working-directory: scripts
run: .\pack.ps1 -verbose -terminal all

- name: Upload artifact (cmder_win_mini.zip)
uses: actions/upload-artifact@v3
with:
path: build/cmder_win_mini.zip
name: cmder_win_mini.zip
if-no-files-found: error

- name: Upload artifact (cmder_win.7z)
uses: actions/upload-artifact@v3
with:
path: build/cmder_win.7z
name: cmder_win.7z
if-no-files-found: error

- name: Upload artifact (cmder_win.zip)
uses: actions/upload-artifact@v3
with:
path: build/cmder_win.zip
name: cmder_win.zip
if-no-files-found: error

- name: Upload artifact (cmder_wt.zip)
uses: actions/upload-artifact@v3
with:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

- Fixes #2940

### Adds

- Cmder for Windows
- Uses Windows and Git for Windows Native Terminals.
- Does not contain a terminal emulator like ConEmu or Windows Terminal.

## [1.3.20](https://github.com/cmderdev/cmder/tree/v1.3.20) (2022-03-18)

### Changes
Expand Down
3 changes: 3 additions & 0 deletions launcher/CmderLauncher.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
<ItemGroup>
<ClCompile Include="src\CmderLauncher.cpp" />
</ItemGroup>
<ItemGroup>
<Image Include="..\icons\cmder.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
170 changes: 120 additions & 50 deletions launcher/src/CmderLauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ bool FileExists(const wchar_t * filePath)

void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstring taskName = L"", std::wstring title = L"", std::wstring iconPath = L"", std::wstring cfgRoot = L"", bool use_user_cfg = true, std::wstring conemu_args = L"")
{
#if USE_TASKBAR_API
wchar_t appId[MAX_PATH] = { 0 };
#endif
#if USE_TASKBAR_API
wchar_t appId[MAX_PATH] = { 0 };
#endif
wchar_t exeDir[MAX_PATH] = { 0 };
wchar_t icoPath[MAX_PATH] = { 0 };
wchar_t cfgPath[MAX_PATH] = { 0 };
Expand All @@ -131,8 +131,17 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
wchar_t windowsTerminalDir[MAX_PATH] = { 0 };
wchar_t conEmuDir[MAX_PATH] = { 0 };
wchar_t winDir[MAX_PATH] = { 0 };
wchar_t emulatorPath[MAX_PATH] = { 0 };

wchar_t vendorDir[MAX_PATH] = { 0 };
wchar_t initCmd[MAX_PATH] = { 0 };
wchar_t initPowerShell[MAX_PATH] = { 0 };
wchar_t initBash[MAX_PATH] = { 0 };
wchar_t initMintty[MAX_PATH] = { 0 };
wchar_t vendoredGit[MAX_PATH] = { 0 };
wchar_t amdx64Git[MAX_PATH] = { 0 };
wchar_t x86Git[MAX_PATH] = { 0 };
wchar_t programFiles[MAX_PATH] = { 0 };
wchar_t programFilesX86[MAX_PATH] = { 0 };
wchar_t minTTYPath[MAX_PATH] = { 0 };

std::wstring cmderStart = path;
std::wstring cmderTask = taskName;
Expand All @@ -144,9 +153,9 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr

GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
wcscpy_s(appId, exeDir);
#endif
#if USE_TASKBAR_API
wcscpy_s(appId, exeDir);
#endif

PathRemoveFileSpec(exeDir);

Expand Down Expand Up @@ -255,8 +264,9 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
}
}

PathCombine(windowsTerminalDir, exeDir, L"vendor\\windows-terminal");
PathCombine(conEmuDir, exeDir, L"vendor\\conemu-maximus5");
PathCombine(vendorDir, exeDir, L"vendor");
PathCombine(windowsTerminalDir, vendorDir, L"windows-terminal");
PathCombine(conEmuDir, vendorDir, L"conemu-maximus5");
GetEnvironmentVariable(L"WINDIR", winDir, MAX_PATH);

if (PathFileExists(windowsTerminalDir))
Expand Down Expand Up @@ -319,7 +329,7 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(cpuCfgPath, cfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir)) {
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy config/windows_terminal_%COMPUTERNAME%_settings.json file to vendor/windows-terminal/settings/settings.json! Access Denied."
Expand All @@ -346,7 +356,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(cfgPath, userCfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/windows-terminal/settings/settings.json file to config/windows_terminal_settings.json! Access Denied."
Expand All @@ -367,7 +378,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(userCfgPath, cfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy config/user_windows_terminal_settings.json file to vendor/windows-terminal/settings/settings.json! Access Denied."
Expand Down Expand Up @@ -395,7 +407,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(cfgPath, userCfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/windows-terminal/settings/settings.json file to config/user_windows_terminal_settings.json! Access Denied."
Expand All @@ -415,7 +428,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(defaultCfgPath, cfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/windows-terminal_default_settings_settings.json file to vendor/windows-terminal/settings/settings.json! Access Denied."
Expand All @@ -437,7 +451,7 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! Access Denied."
? L"Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! Access Denied."
: L"Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml!", MB_TITLE, MB_ICONSTOP);
exit(1);
}
Expand All @@ -446,7 +460,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if (!CopyFile(cfgPath, userCfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/windows-terminal/settings/settings.json file to config/user_windows_terminal_settings_settings.json! Access Denied."
Expand All @@ -469,7 +484,8 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
{
if ( ! CopyFile(defaultCfgPath, userCfgPath, FALSE))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL,
(GetLastError() == ERROR_ACCESS_DENIED)
? L"Failed to copy vendor/windows-terminal_default_settings_settings.json file to [user specified path]/config/user_windows_terminal_settings.json! Access Denied."
Expand All @@ -488,22 +504,50 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
PathCombine(userConEmuCfgPath, userConfigDirPath, L"user-ConEmu.xml");
}

GetEnvironmentVariable(L"ProgramFiles", programFiles, MAX_PATH);
GetEnvironmentVariable(L"ProgramFiles(x86)", programFilesX86, MAX_PATH);

PathCombine(vendoredGit, vendorDir, L"git-for-windows");
PathCombine(amdx64Git, programFiles, L"Git");
PathCombine(x86Git, programFilesX86, L"Git");

SYSTEM_INFO sysInfo;
GetNativeSystemInfo(&sysInfo);
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
PathCombine(terminalPath, exeDir, L"vendor\\windows-terminal\\WindowsTerminal.exe");
}
else if (PathFileExists(conEmuDir))
{
swprintf_s(args, L"%s /Icon \"%s\"", args, icoPath);
swprintf_s(args, L"%s /title \"%s\"", args, cmderTitle.c_str());
PathCombine(terminalPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu64.exe");
}
else
{
PathCombine(terminalPath, winDir, L"system32\\cmd.exe");
}

if (!PathFileExists(windowsTerminalDir)) {
swprintf_s(args, L"%s /Icon \"%s\"", args, icoPath);
if (streqi(cmderTask.c_str(), L"powershell"))
{
PathCombine(terminalPath, winDir, L"System32\\WindowsPowerShell\\v1.0\\powershell.exe");
}
/*
else if (streqi(cmderTask.c_str(), L"mintty"))
{
if (PathFileExists(vendoredGit))
{
PathCombine(terminalPath, vendoredGit, L"git-bash.exe");
}
else if (PathFileExists(amdx64Git))
{
PathCombine(terminalPath, amdx64Git, L"git-bash.exe");
}
else if (PathFileExists(x86Git))
{
PathCombine(terminalPath, x86Git, L"git-bash.exe");
}
}
*/
}

if (!streqi(cmderStart.c_str(), L""))
Expand All @@ -524,13 +568,6 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
}
}

if (!streqi(cmderTitle.c_str(), L""))
{
if (!PathFileExists(windowsTerminalDir)) {
swprintf_s(args, L"%s /title \"%s\"", args, cmderTitle.c_str());
}
}

if (cfgRoot.length() != 0)
{
if (!PathFileExists(windowsTerminalDir)) {
Expand All @@ -546,6 +583,11 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
// The `/run` arg and its value MUST be the last arg of ConEmu
// see : https://conemu.github.io/en/ConEmuArgs.html
// > This must be the last used switch (excepting -new_console and -cur_console)
PathCombine(initCmd, vendorDir, L"init.bat");
PathCombine(initPowerShell, vendorDir, L"profile.ps1");
PathCombine(initBash, vendorDir, L"start_git_bash.cmd");
PathCombine(initMintty, vendorDir, L"start_git_mintty.cmd");

if (!streqi(cmderTask.c_str(), L""))
{
if (PathFileExists(windowsTerminalDir)) {
Expand All @@ -557,7 +599,22 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
}
else
{
swprintf_s(args, L"%s %s", args, cmderTask.c_str());
if (streqi(cmderTask.c_str(), L"powershell"))
{
swprintf_s(args, L"%s -ExecutionPolicy Bypass -NoLogo -NoProfile -NoExit -Command \"Invoke-Expression 'Import-Module ''%s'''\"", args, initPowerShell);
}
else if (streqi(cmderTask.c_str(), L"bash"))
{
swprintf_s(args, L"%s /c \"%s\"", args, initBash);
}
else if (streqi(cmderTask.c_str(), L"mintty"))
{
swprintf_s(args, L"%s /c \"%s\"", args, initMintty);
}
else if (streqi(cmderTask.c_str(), L"cmder"))
{
swprintf_s(args, L"%s /k \"%s\"", args, initCmd);
}
}
}

Expand All @@ -568,23 +625,42 @@ void StartCmder(std::wstring path = L"", bool is_single_mode = false, std::wstr
SetEnvironmentVariable(L"CMDER_USER_BIN", userBinDirPath);
}

// Try to find m'intty.exe' so ConEmu can launch using %MINTTY_EXE% in external Git for Cmder Mini.
// See: https://github.com/Maximus5/ConEmu/issues/2559 for why this is commented.

/*
if (PathFileExists(vendoredGit))
{
PathCombine(minTTYPath, vendoredGit, L"usr\\bin\\mintty.exe");
SetEnvironmentVariable(L"MINTTY_EXE", minTTYPath);
}
else if (PathFileExists(amdx64Git))
{
PathCombine(minTTYPath, amdx64Git, L"usr\\bin\\mintty.exe");
SetEnvironmentVariable(L"MINTTY_EXE", minTTYPath);
}
else if (PathFileExists(x86Git))
{
PathCombine(minTTYPath, x86Git, L"usr\\bin\\mintty.exe");
SetEnvironmentVariable(L"MINTTY_EXE", minTTYPath);
}
*/

// Ensure EnvironmentVariables are propagated.

STARTUPINFO si = { 0 };

si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
si.lpTitle = appId;
si.dwFlags = STARTF_TITLEISAPPID;
#endif
#if USE_TASKBAR_API
si.lpTitle = appId;
si.dwFlags = STARTF_TITLEISAPPID;
#endif
PROCESS_INFORMATION pi;

// MessageBox(NULL, terminalPath, _T("Error"), MB_OK);
// MessageBox(NULL, args, _T("Error"), MB_OK);

if (!CreateProcess(terminalPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi))
{
if (PathFileExists(windowsTerminalDir)) {
if (PathFileExists(windowsTerminalDir))
{
MessageBox(NULL, _T("Unable to create the Windows Terminal process!"), _T("Error"), MB_OK);
}
else if (PathFileExists(conEmuDir))
Expand Down Expand Up @@ -729,15 +805,13 @@ cmderOptions GetOption()
wchar_t conEmuDir[MAX_PATH] = { 0 };
wchar_t vendorDir[MAX_PATH] = { 0 };
wchar_t exeDir[MAX_PATH] = { 0 };
wchar_t cmdInit[MAX_PATH] = { 0 };

GetModuleFileName(NULL, exeDir, sizeof(exeDir));
PathRemoveFileSpec(exeDir);

PathCombine(vendorDir, exeDir, L"vendor");
PathCombine(windowsTerminalDir, vendorDir, L"windows-terminal");
PathCombine(conEmuDir, vendorDir, L"ConEmu-Maximus5");
PathCombine(cmdInit, vendorDir, L"init.bat");

szArgList = CommandLineToArgvW(GetCommandLine(), &argCount);

Expand Down Expand Up @@ -868,14 +942,11 @@ cmderOptions GetOption()
cmderOptions.error = true;
}
}

}

if (!PathFileExists(windowsTerminalDir) && !PathFileExists(conEmuDir))
if (!PathFileExists(windowsTerminalDir) && !PathFileExists(conEmuDir) && streqi(cmderOptions.cmderTask.c_str(), L""))
{
cmderOptions.cmderTask = L"/k \"";
cmderOptions.cmderTask += cmdInit;
cmderOptions.cmderTask += L"\"";
cmderOptions.cmderTask = L"cmder";
}

if (cmderOptions.error == true)
Expand Down Expand Up @@ -909,13 +980,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,

GetModuleFileName(NULL, exeDir, sizeof(exeDir));
PathRemoveFileSpec(exeDir);

PathCombine(windowsTerminalDir, exeDir, L"vendor\\windows-terminal");
PathCombine(windowsTerminalDir, exeDir, L"vendor\\windows-terminal");

if (cmderOptions.registerApp == true)
{
if (PathFileExists(windowsTerminalDir))
{
if (PathFileExists(windowsTerminalDir))
{
RegisterShellMenu(cmderOptions.cmderRegScope, SHELL_MENU_REGISTRY_PATH_BACKGROUND, cmderOptions.cmderCfgRoot, cmderOptions.cmderSingle);
RegisterShellMenu(cmderOptions.cmderRegScope, SHELL_MENU_REGISTRY_PATH_LISTITEM, cmderOptions.cmderCfgRoot, cmderOptions.cmderSingle);
RegisterShellMenu(cmderOptions.cmderRegScope, SHELL_MENU_REGISTRY_DRIVE_PATH_BACKGROUND, cmderOptions.cmderCfgRoot, cmderOptions.cmderSingle);
Expand Down Expand Up @@ -946,4 +1016,4 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}

return 0;
}
}
Loading
Loading