Skip to content

fix timer and singlequote #11

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

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@

# Static compilation
```powershell
# compile release
& 'C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe' /m:8 /property:Configuration=Release .\singleinstance.sln

# check dll depends
&'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\dumpbin.exe' /dependents .\Release\singleinstance.exe
```

# context-menu-launcher
Select multiple files from Windows Explorer menu and launch just one instance of process

[Download executable](https://github.com/zenden2k/context-menu-launcher/releases/tag/1.0)
[Download executable](https://github.com/owenstake/context-menu-launcher/releases/download/latest/singleinstance.exe)

## How to pass multiple files to shell context menu command (Windows Explorer)

Expand Down
71 changes: 42 additions & 29 deletions singleinstance/singleinstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,34 @@ Windows Registry Editor Version 5.00

*/
#include <Shellapi.h>
#include <atomic>
#include <vector>
#include <string>
#include <regex>

class CLimitSingleInstance {
protected:
DWORD m_dwLastError;
HANDLE m_hMutex;
protected:
DWORD m_dwLastError;
HANDLE m_hMutex;

public:
CLimitSingleInstance(TCHAR *strMutexName)
{
m_hMutex = CreateMutex(NULL, FALSE, strMutexName); //do early
m_dwLastError = GetLastError(); //save for use later...
}

~CLimitSingleInstance(){
if (m_hMutex) //Do not forget to close handles.
public:
CLimitSingleInstance(TCHAR *strMutexName)
{
CloseHandle(m_hMutex); //Do as late as possible.
m_hMutex = NULL; //Good habit to be in.
m_hMutex = CreateMutex(NULL, FALSE, strMutexName); //do early
m_dwLastError = GetLastError(); //save for use later...
}
}

BOOL IsAnotherInstanceRunning(){
return (ERROR_ALREADY_EXISTS == m_dwLastError);
}
~CLimitSingleInstance(){
if (m_hMutex) //Do not forget to close handles.
{
CloseHandle(m_hMutex); //Do as late as possible.
m_hMutex = NULL; //Good habit to be in.
}
}

BOOL IsAnotherInstanceRunning(){
return (ERROR_ALREADY_EXISTS == m_dwLastError);
}
};

int timeout = 400; // ms
Expand Down Expand Up @@ -158,13 +160,19 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
return TRUE;
}

void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine, bool Force){
void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine, bool Force, bool singlequote){
wchar_t mark;
if (singlequote) {
mark = L'\'';
} else {
mark = L'"';
}
if (Force == false &&
Argument.empty() == false &&
Argument.find_first_of(L" \t\n\v\"") == Argument.npos) {
CommandLine.append(Argument);
} else {
CommandLine.push_back(L'"');
CommandLine.push_back(mark);

for (auto It = Argument.begin();; ++It) {
unsigned NumberBackslashes = 0;
Expand Down Expand Up @@ -196,7 +204,7 @@ void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine, bool For
}
}

CommandLine.push_back(L'"');
CommandLine.push_back(mark);
}
CommandLine.push_back(L' ');
}
Expand All @@ -205,18 +213,22 @@ void LaunchApp() {
std::wstring cmdLine;

for (int i = 3; i < argCount; i++) {
if (!lstrcmp(szArgList[i], _T("$files"))) {
std::wstring argStr = szArgList[i];
std::size_t found = argStr.find(L"$files");
if (found!=std::string::npos) {
std::wstring tmpstr;
for (const auto& file : files) {
ArgvQuote(file, cmdLine, true);
ArgvQuote(file, tmpstr, true, true);
}
} else if (!lstrcmp(szArgList[i], _T("--si-timeout"))) {
argStr = std::regex_replace(argStr, std::wregex(L"\\$files"), tmpstr);
cmdLine.append(argStr);
} else if (argStr == L"--si-timeout") {
i++; // skip
}
else {
ArgvQuote(szArgList[i], cmdLine, true);
} else {
ArgvQuote(argStr, cmdLine, true, false);
}
}
//MessageBox(0, cmdLine.c_str(), szArgList[2], 0);
// MessageBox(0, cmdLine.c_str(), szArgList[2], 0);
HINSTANCE hinst = ShellExecute(0, _T("open"), szArgList[2], cmdLine.c_str(), 0, SW_SHOWNORMAL);
if (reinterpret_cast<int>(hinst) <= 32) {
TCHAR buffer[256];
Expand All @@ -237,6 +249,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
SetTimer(hWnd, TIMER_ID, timeout, 0);
break;
case WM_COPYDATA:
SetTimer(hWnd, TIMER_ID, timeout, 0);
pcds = reinterpret_cast<COPYDATASTRUCT*>(lParam);
if (pcds->dwData == 1) {
LPCTSTR lpszString = reinterpret_cast<LPCTSTR>(pcds->lpData);
Expand All @@ -255,4 +268,4 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
}
5 changes: 3 additions & 2 deletions singleinstance/singleinstance.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@
<ProjectGuid>{95C5CED1-7955-43FC-9EA3-E20D2CE1DEB1}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>singleinstance</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
Expand Down