I need to open html file on disk with parameters from within my C++ program in default browser.
For example: c:\index.html?id=15 .
I am using ShellExecute, to open all urls or files, but this one does not work, it strips parameters from local files.
ShellExecute(0, NULL, "file:///c:\index.html?id=15", NULL, NULL, SW_SHOWNORMAL);
It works fine from command line i.e.
iexplore file:///c:\index.html?id=15
How can I open that page?
Please try this code.
int result = 0;
TCHAR app[MAX_PATH] = { 0 };
result = (int)::FindExecutable(_T("C:\\index.html"), NULL, app);
if (result > 32) {
::ShellExecute(0, NULL, app,
_T("file:///C:\\index.html?id=15"), NULL, SW_SHOWNORMAL);
}
Related
I am able to open PDF file with the below code in flutter windows platform,
Process.run(
'C:\\Program Files\\Adobe\\Acrobat DC\\Acrobat\\Acrobat.exe', [_path]);
My problem is specifying the path to the app, it can be different!
Is there a way to open the file automatically with the Windows Standard App?
For example: .pdf files with Acrobath Reader, .txt files with Notepad, .csv with Excel ....etc
Thx for Help!
The Win32 API for this is ShellExecute
https://pub.dev/documentation/win32/latest/win32/ShellExecute.html
Example:
final verb = 'open'.toNativeUtf16();
final file = 'yourfile.pdf'.toNativeUtf16();
final params = ''.toNativeUtf16();
final path = 'C:\yourfolder\'.toNativeUtf16();
ShellExecute(0, verb, file, params, path, SW_SHOW);
The new answer is (I only care about Windows):
// incoming path uses forward slashes
Future<void> launchFile(String path, String file) async {
if (file.isEmpty) {
path = path.replaceAll("/", "\\"); // necessary for Windows
await Process.start('explorer', [path]);
}
else {
ProcessResult result = await
Process.run('cmd', ['/c', 'start', '', '$path/$file']);
if (result.exitCode == 0) {
// good
}
else {
// bad
}
}
}
The /c will close the cmd window after launch. Explorer seems to prefer backslashes.
I asked ChatGPT to tell me how to deal with spaces in filenames because I could not figure it out. Apparently I needed an empty parameter after 'start'.
Code is minimal to show the basics; add your own error detection/handling, etc.
I have a windows service that creates a JobObject that i need to keep alive as long as the machine is turned on - the goal is to manage a few user session processes that can terminate/start at any time with this JobObject. I am creating it in a service to make sure the process is running at startup, and that it can't be killed by regular users.
However, i don't seem to be able to open a handle to this JobObject from the user session, I always get an access denied (5) error, despite going as far as creating it with a NULL DACL.
I have found a somewhat related question here: Open an Event object created by my service from my application, but for me, even with the NULL DACL, when asking for a JOB_OBJECT_ASSIGN_PROCESS right, i get access denied (asking for SYNCHRONIZE works for example).
The service code:
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE);
SECURITY_ATTRIBUTES secAttr= {0};
secAttr.nLength = sizeof(secAttr);
secAttr.bInheritHandle = false;
secAttr.lpSecurityDescriptor = psd;
hJobObject = CreateJobObject(&secAttr, SCL_JOBOBJECTNAME);
LocalFree(psd);
The user session code:
hJobObject = OpenJobObject(JOB_OBJECT_ASSIGN_PROCESS, FALSE, SCL_JOBOBJECTNAME);
if (hJobObject == NULL)
{
DWORD wError = GetLastError();
printf("Error: %d\n", wError); // this always pops 5
return 1;
}
Any ideas? As a test, i tried spawning a user session process from within the service, and assign the JobObject via the service code, and that worked,.. so i'm fairly certain its related to security settings i am missing, despite the NULL DACL.
if you create Job in service - this object by default will be have WinSystemLabelSid label SID: S-1-16-16384 - System Mandatory Level. (i just check this) so you need not only set Dacl but Sacl too. for example:
ULONG cb = MAX_SID_SIZE;
PSID LowLabelSid = (PSID)alloca(MAX_SID_SIZE);
if (CreateWellKnownSid(WinLowLabelSid, 0, LowLabelSid, &cb))
{
PACL Sacl = (PACL)alloca(cb += sizeof(ACL) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
InitializeAcl(Sacl, cb, ACL_REVISION);
if (AddMandatoryAce(Sacl, ACL_REVISION, 0, 0, LowLabelSid))
{
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE);
SECURITY_ATTRIBUTES sa= { sizeof(sa), &sd, FALSE };
if (HANDLE hJob = CreateJobObject(&sa, L"Global\\{58BFC6DB-BE93-4cdb-919C-4C713ACB5A32}"))
{
CloseHandle(hJob);
}
}
}
I've been banging my head on this for days, and I must have read every page on the Internet even remotely related, but I still can't find an answer. Help!
Here's the scenario: In Windows 7, I have a process running under an admin user account (not a service). It creates a global named mutex, which is later used in a child process running under a regular user account. No matter what I do, or what ACLs I put on the mutex, the child process keeps returning Access Denied when trying to get the handle.
I've distilled my code down into a test app just to experiment with the process and mutex parts, and I found something surprising: if I call OpenMutex from the user app without first creating the mutex, I would expect a Not Found error but I still get Access Denied. However, if I launch the user app from Explorer instead (shift-right-click, Run as different user...), I get the expected behavior. I also noticed that the user app has a plain blocky window border rather than the normal Windows theme when launched from the admin app.
So my guess is that there's something wrong with how I'm launching the user app, but I just can't see what I'm missing.
Here are the relevant parts:
bool CUserTest::LogInUser()
{
if ((m_hUserToken == NULL) && !LogonUser(TEST_USER_NAME, L".", TEST_USER_PASS, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &m_hUserToken))
{
CloseHandle(m_hUserToken);
m_hUserToken = NULL;
}
return (m_hUserToken != NULL);
}
bool CUserTest::LaunchTestApp()
{
PROCESS_INFORMATION ProcInfo;
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(si);
si.lpDesktop = L"winsta0\\default";
wchar_t wszCmdLine[MAX_PATH + 1] = { 0 };
wcscpy(wszCmdLine, L"UserTestClient.exe");
bool bSuccess = false;
LPVOID pEnv;
PROFILEINFO sProfileInfo;
ZeroMemory(&sProfileInfo, sizeof(PROFILEINFO));
sProfileInfo.dwSize = sizeof(PROFILEINFO);
sProfileInfo.lpUserName = TEST_USER_NAME;
if (LoadUserProfile(m_hUserToken, &sProfileInfo))
{
if (ImpersonateLoggedOnUser(m_hUserToken))
{
if (CreateEnvironmentBlock(&pEnv, m_hUserToken, FALSE))
{
bSuccess = CreateProcessAsUser(
m_hUserToken,
NULL,
wszCmdLine,
NULL, // ProcessAttributes
NULL, // ThreadAttributes
FALSE, // InheritHandles
CREATE_UNICODE_ENVIRONMENT, // CreationFlags
pEnv, // Environment
NULL, // CurrentDirectory
&si,
&ProcInfo); // ProcessInformation
DestroyEnvironmentBlock(pEnv);
}
RevertToSelf();
}
UnloadUserProfile(m_hUserToken, sProfileInfo.hProfile);
}
if (bSuccess)
{
CloseHandle(ProcInfo.hThread);
CloseHandle(ProcInfo.hProcess);
}
return bSuccess;
}
I never could get the CreateProcessAsUser call to work correctly, but I finally got it working using CreateProcessWithLogonW instead. The trick was to set si.lpDesktop to NULL rather than "winsta0\default", contrary to everything I'd read up to this point.
win7 OS, vs2008.
My program disappears when shellexcute was called,
It's a WTL project and the code like these:
*.h
COMMAND_HANDLER(IDC_BTN_LOGIN, BN_CLICKED, DoLogin)
*.cpp
LRESULT XLoginView::DoLogin(WORD, WORD, HWND, BOOL&)
{
::ShellExecute(NULL, _T("open"), _T("http://mysite.com/login.php"), NULL,NULL, SW_SHOW);
return 0;
}
when the login button was clicked, then my program was disappeard and the visual studio exit too.
Even the code is such simple as these:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
ShellExecute(NULL, L"open", L"http://stackoverflow.com", NULL, NULL, SW_SHOW);
}
return nRetCode;
}
The site (http://stackoverflow.com) was openned only the first running or debugging, then the second time and over, the visual studio disappears at the same time.
Here is a same problem, but didn't give the reason
http://bbs.pediy.com/showthread.php?t=130968
update 2013-08-27
As IInspectable's suggestion, it works ok with local resource, but web resource.
Google Chrome is my default browser, so I trust some other browsers as default browser, then get these result below:
(1) Default browser: Google Chrome
If I directly run my program, it is ok, it works. The web resource(URL) was openned, the program doesn't crush.
But if I debug the program from visual studio's button "start debugging", not only the program exit but also visual studio exit when the button who's event code calls "ShellExcute".
(2) Default browser: Firfox or Internet Explorer
The program works, it doesn't crush or disappear whenever I run it directly or debug it from visual studio.
As the above I think maybe it's because the program's Privilege is not enough.
so I trust the code below, then the problem disappeared.
void UpPrivilege()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, L"SeDebugPrivileges", &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
}
update 2013-08-27
As IInspectable's suggestion, it works ok with local resource, but web resource.
Google Chrome is my default browser, so I trust some other browsers as default browser, then get these result below:
(1) Default browser: Google Chrome
If I directly run my program, it is ok, it works. The web resource(URL) was openned, the program doesn't crush.
But if I debug the program from visual studio's button "start debugging", not only the program exit but also visual studio exit when the button who's event code calls "ShellExcute".
(2) Default browser: Firfox or Internet Explorer
The program works, it doesn't crush or disappear whenever I run it directly or debug it from visual studio.
As the above I think maybe it's because the program's Privilege is not enough.
so I trust the code below, then the problem disappeared.
void UpPrivilege()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, L"SeDebugPrivileges", &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
}
Wikipedia says the following: "On Microsoft Windows, D can access COM (Component Object Model) code."
What kind of support for COM is present in D? Does it make life easier than using COM in C++. I've found this link on the D page but it doesn't tell me too much.
Juno has a new version .5.1 that has lots of great ways of connecting to Word, Excel, FrameMaker, Trados, etc. So, it is possible and easy. Something like this:
scope word = new DispatchObject("Word.Application");
scope wDocs = word.get("Documents");
char[] dd = dir ~ r"\";
char[][] docs = GetFilesFromDir(dir ~ r"\", "*." ~ fromType, true);
if (docs.length == 0)
{
info.text = "Did not find any " ~ std.string.toupper(fromType) ~
" files in the directory... \n\nExiting...";
return;
}
foreach(char[] d; docs)
{
scope wDoc = wDocs.call("Open", d);//"Normal", false, 0);
char[] txt = std.path.getName(d); // original file ie. test if it was test.doc
txt ~= ".doc";
if (std.file.exists(txt))
std.file.remove(txt);
wDoc.call("SaveAs",
txt, // FileName
0, // FileFormat wdFormatDOC = 0
false, // LockComments
"", // Password
false, // AddToRecentFiles
"", // WritePassword
false, // ReadOnlyRecommended
false, // EmbedTrueTypeFonts
false, // SaveNativePictureFormat
false, // SaveFormsData
false, // SaveAsAOCELetter
65001, // Encoding 65001 is UTF8
false, // InsertLineBreaks
false, // AllowSubstitutions
0 // LineEnding Const wdCRLF = 0
);
wDoc.call("Close");
}
word.call("Quit");
The Juno lib, written by John Chapman, contains COM support modules. Unfortunately not up to date with the latest compiler.
http://www.dsource.org/projects/juno/wiki/ComProgramming/ "Juno COM"
Should be part of phobos, beside.
To Hannes J. use auto instead of delphi's var
// Create an instance of IXMLDOMDocument3.
auto doc = DOMDocument60.coCreate!(IXMLDOMDocument3);
scope(exit) doc.Release();
// Create an event provider instance.
auto events = new EventProvider!(XMLDOMDocumentEvents)(doc);
scope(exit) events.Release();
events.bind("onReadyStateChange", {
writefln("state changed");
});
events.bind("onDataAvailable", {
writefln("data available");
});
// Tell the document to load asynchronously.
doc.put_async(com_true);
// Load the XML document.
com_bool result;
doc.load("books.xml".toVariant(true), result);
http://www.digitalmars.com/d/2.0/interface.html#COM-Interfaces
I knew this was somewhere but it took me a while to find it. Basically, COM support in D is a hack on top of interfaces. Apparently the compiler knows about them and treats them as "special" in a few small ways, so everything works. BTW, I thought COM was dead.