I found it a little tricky that some compiler can't run the <windows.h> header file. Is it possible to open an URL in C++ without using <windows.h> ?
Here's my code, but using <windows.h>
#include <windows.h>
#include <shellapi.h>
using namespace std;
int main(){
ShellExecute(NULL,NULL,"https://ssur.cc/Easy-Way-To-Open-URL-In-CPP",NULL,NULL,SW_SHOW );
return 0;
}
You could just forward declare the function in question and let the linker handle it.
But if your compiler has issues with windows.h it will probably not support all Windows platforms/architectures. But assuming the calling-convention used by the compiler just happens to match you can do something like this:
typedef void* M_HINSTANCE;
typedef void* M_HWND;
#define M_SW_SHOW 5
// should be __stdcall , but if your compiler has trouble with windows.h, then it will probably also have trouble with __stdcall
extern "C" M_HINSTANCE ShellExecuteA(M_HWND hwnd,
const char* lpOperation,
const char* lpFile,
const char* lpParameters,const char* lpDirectory,
int nShowCmd
);
int main(){
ShellExecuteA(0,0,"https://ssur.cc/Easy-Way-To-Open-URL-In-CPP",0,0,M_SW_SHOW );
return 0;
}
You will still need to link to Shell32.lib and like I mentioned you might get linker errors on some platforms for mismatching calling conventions.
Alternatively you can try to start the shell as a generic process like
#include <cstdlib>
int main(){
std::system("cmd.exe /c start https://ssur.cc/Easy-Way-To-Open-URL-In-CPP");
// or something like:
// std::system("explorer.exe https://ssur.cc/Easy-Way-To-Open-URL-In-CPP");
// or on some other non-windows platforms:
// std::system("open https://ssur.cc/Easy-Way-To-Open-URL-In-CPP");
return 0;
}
Related
I have written a downloader program in C++ using urlmon.dll.
I have used Visual Studio 2015 RTM as the IDE.
Here are my codes:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "clocale"
#include "fstream"
#include "iostream"
#include "string"
using namespace std;
typedef int*(*tdDosyaIndir)(void*, char*, char*, DWORD, void*);
int main()
{
setlocale(LC_ALL, "turkish");
string strAdres;
cout << "İndirilecek adresi girin:\n";
cin >> strAdres;
HINSTANCE dll = LoadLibrary(L"urlmon.dll");
tdDosyaIndir DosyaIndir = (tdDosyaIndir)GetProcAddress(dll, "URLDownloadToFileA");
DosyaIndir(0, &strAdres[0u], "dosya.html", 0, 0);
FreeLibrary(dll);
return 0;
}
But the problem is when I try to download something program shows this error:
What should I do in order to fix this issue?
You need to specify the calling convention in the function pointer typedef.
Windows API functions generally use the __stdcall calling convention. However, C and C++ functions typically use the __cdecl calling convention, and that is the compiler's default. When there is a mismatch of the calling convention, the compiler generates the wrong code, and you get this error message.
To ensure the compiler generates the correct code to call the function, your typedef for it should look like this:
typedef HRESULT (__stdcall *tdDosyaIndir)(void*, char*, char*, DWORD, void*);
Intro
First of all, I would like to say that I have read through the previous answers for this type of question, including this excellently written one.
However, I do not understand enough about C++ to be able to use the more "advanced" fixes.
I have ensured that the right type of console has been selected (Console (/SUBSYSTEM:CONSOLE) for those interested), and have the required imports with the possible exception of an IDL mentioned somewhere (that falls into the lack of understanding category).
If this is a duplicate, I would be more than happy to use the post I duplicated, but I have not been able to find anything that can help someone of my skill level.
Technical Information
IDE: Visual Studio
Platform: Windows
Code
headers.h
#pragma once
#include <stdio.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <Shobjidl.h>
#include <time.h>
#include <stdlib.h>
#include <tchar.h>
main.cpp
#include "headers.h"
using namespace std;
int main() {
string x = "C://Users/student/Desktop/i-should-buy-a-boat.jpg";
x.c_str();
wstring tempx = std::wstring(x.begin(), x.end());
LPCWSTR sw = tempx.c_str();
HRESULT SetWallpaper(
LPCWSTR monitorID,
LPCWSTR wallpaper
);
SetWallpaper(NULL, sw);
}
SetWallpaper() is not a standalone function exported by the Win32 API. It is a method of the IDesktopWallpaper interface (see here).
So you need to use code that is more like this instead:
#include "headers.h"
int main()
{
std::wstring x = L"C:\\Users\\student\\Desktop\\i-should-buy-a-boat.jpg";
CoInitialize(NULL);
IDesktopWallpaper *p;
if (SUCCEEDED(CoCreateInstance(__uuidof(DesktopWallpaper), 0, CLSCTX_LOCAL_SERVER, __uuidof(IDesktopWallpaper), (void**)&p)))
{
p->SetWallpaper(NULL, x.c_str());
p->Release();
}
CoUninitialize();
return 0;
}
I am trying to intercept open system call in Linux. It works fine with other libraries but doesn't wotk with boost libboost_fileystem. Here is my code (stripped down for readability).
#include <boost/filesystem/fstream.hpp>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
using namespace std;
using namespace boost::filesystem;
typedef int (*open_func_type)(const char * pathname, int flags, ...);
int open(const char *path, int flags, ...)
{
va_list arg;
mode_t mode = 0;
if (flags & O_CREAT)
{
va_start(arg, flags);
mode = va_arg(arg, mode_t);
va_end(arg);
}
//some stuff here
open_func_type open_func = (open_func_type) dlsym(RTLD_NEXT, "open");
return open_func(path, flags, mode);
}
int main()
{
boost::filesystem::fstream build_path;
build_path.open("/tmp/test.txt", ios::in);
//other stuff
return 0;
}
I stepped though the code using gdb, my open implementation doesn't get called. But doing strace shows the open system call being called. If I call other library functions that call open, I see my implementation getting called. Anything that I am doing wrong here? I am dynamically linking with boost libraries.
I gave sometime to figure it out and found that internally boost calls std::basic_filebuf open which in turn calls fopen. fopen seems to call open system call in the kernel without calling open library call (it would be nice if somebody could point it out why). I intercepted fopen call and this works fine now. If large file support is used, fopen64 also needs to be implemented.
at the beginning I have:
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <string>
#define _WIN32_WINNT 0x500 //tells that this is win 2000 or higher, without GetConsoleWindow would not work
#include <windows.h>
using namespace std;
int main() {
PCONSOLE_FONT_INFO lpConsoleCurrentFont;
GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), false, lpConsoleCurrentFont);
return 0;
}
And undocumented function SetConsoleFont works, but GetCurrentConsoleFont fails at compilation saying that it was not declared in this scope.
-- edit: changed to self sustained code.
GetCurrentConsoleFont is exported on NT4+ at least, the MinGW headers must be wrong.
Try adding this code after your #include's:
#ifdef __cplusplus
extern "C" {
#endif
BOOL WINAPI GetCurrentConsoleFont(HANDLE hConsoleOutput,BOOL bMaximumWindow,PCONSOLE_FONT_INFO lpConsoleCurrentFont);
#ifdef __cplusplus
}
#endif
Your code is also wrong, it should be:
CONSOLE_FONT_INFO ConsoleFontInfo;
GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), false, &ConsoleFontInfo);
(Any time you see PSOMETYPE as a parameter you usually allocate a SOMETYPE struct on the stack and pass a pointer to this struct as the parameter)
Hans comment above is correct. GetCurrentConsoleFont is not defined in wincon.h. Add the following lines to wincon.h to get this functionality:
BOOL WINAPI GetCurrentConsoleFont(HANDLE, BOOL, PCONSOLE_FONT_INFO );
COORD WINAPI GetConsoleFontSize( HANDLE, DWORD );
GetConsoleFontSize was also missing.
First, I create a simple dll called SimpleDll.dll, its head file:
// SimpleDll.h
#ifdef MYLIBAPI
#else
#define MYLIBAPI __declspec(dllimport)
#endif
MYLIBAPI int Add(int a. int b);
its source code:
// SimpleDll.c
#include <windows.h>
#define MYLIBAPI __declspec(dllexport)
#include "SimpleDll.h"
int Add(int a, int b)
{
return a + b;
}
Then I call it in another project, and it works fine:
// TestSimpleDll.c
#include "stdafx.h"
#include <windows.h>
#include "SimpleDll.h"
#pragma comment(lib, "SimpleDll.lib")
int _tmain(int argc, _TCHAR* argv[])
{
printf("%d", Add(10, 30)); // Give the expected result 40
return 0;
}
However, when I call GetProcAddress to get it's address, it doesn't work!
// TestSimpleDll2.c
#include "stdafx.h"
#include <windows.h>
#include "SimpleDll.h"
#pragma comment(lib, "SimpleDll.lib")
int _tmain(int argc, _TCHAR* argv[])
{
printf("%d", Add(10, 30)); // Give the expected result 40
HMODULE hModule = GetModuleHandleA("SimpleDll.dll"); // hModule is found
PROC add_proc = GetProcAddress(hModule, "Add"); // but Add is not found !
// add_proc is NULL!
return 0;
}
Thanks for your help. (PS: I use VS2010 on Windows7)
Update:
This is what the depedency walker show for the SimpleDll.dll file:
You should use a .def file if you want to export the name for GetProcAddress. Otherwise you will have to deal with c++ name mangling and with symbol decorations.
You can avoid mangling by declaring your function as extern "C", but the only way to avoid decorations is to use a .DEF file.
One more thing - in Dependency walker - use F10 to toggle between decorated and undecorated names.
Dependency Walker is an excellent tool for troubleshooting DLL issues like this.
I'm assuming you are compiling the DLL as C code. Otherwise, C++ performs name mangling that would cause problems.
To avoid name mangling simply wrap the export definition in extern "C".
extern "C" {
MYLIBAPI int Add(int a. int b);
}