-2

Currently I'm using windows 8.1.... in C++ when I'm trying to create a file on desktop with these codes ...

#include "stdafx.h"
#include <fstream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    ofstream myfile("C:/Users/%USERPROFILE%/Desktop/myfile.anything");
    //ofstream myfile("C:/users/myfile.anything"); //Works fine with run As Administrator
    return 0;
}

so the problems are completely clear 1.the userprofile don't know why? and 2.i should run the program as administrator but in here there is no need for run as.... i wanted to know if there is a little more simple way .... Thanks

Community
  • 1
  • 1
  • 2
    `%USERPROFILE%` This substitution will not work in c++ as part of a path. It will not use explorer to expand shell variables. – drescherjm Jan 03 '15 at 23:24
  • `&USERPROFILE&` isn't proper batch variable referencing (it should be `%USERPROFILE%`), and I think you will have to actually get the value of that variable from the environment, rather than use it directly in the path. – Ryan J Jan 03 '15 at 23:24
  • 2
    c++ has no notion of things like a _"desktop"_! – πάντα ῥεῖ Jan 03 '15 at 23:33
  • Never hard code the path to a folder like Desktop. It may be redirected. Use SHGetKnownFolderPath instead. – Helge Klein Jan 04 '15 at 00:17

3 Answers3

1

As the comments point out, you're trying to use an environment variable in your filepath, and the standard iostreams don't do environment variable expansion. You'll have to do that part yourself with platform-specific code, or simply use "normal" filepaths.

For C++ on Windows, the function to do this is GetEnvironmentVariable. It's one of those functions that takes a fixed size buffer, so using it is finicky enough that there's already a stackoverflow question all about how to call it correctly.

P.S. As the comments also pointed out, in places that do perform environment variable expansion (such as shell scripts or Windows Explorer), it's actually %USERPROFILE%, not &USERPROFILE&.

Ixrec
  • 966
  • 1
  • 7
  • 20
1

The comments to the other question were correct. Here's a basic way of fixing this (using http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx)

#include <fstream>
#include <Windows.h>
#include <string>
using namespace std;

int main() {
    WCHAR *buffer = new WCHAR[260];
    const WCHAR name[12] = "USERPROFILE";
    DWORD result = GetEnvironmentVariable(name, buffer, 260);
    if (result > 260) {
        delete[] buffer; buffer = new WCHAR[result];
        GetEnvironmentVariable(name, buffer, result);
    }
    wstring s("C:/Users/");
    s += buffer;
    s += "/Desktop/myfile.anything";
    ofstream myfile(s.c_str());
    // do things here
    delete[] buffer;
    return 0;
}
Rahul Manne
  • 1,229
  • 10
  • 20
1

You have many ways to get user profile directory :

  • via the environment variable USERPROFILE :

    #include <cstdlib>
    ...
    string profile = getenv("USERPROFILE");
    
  • via Windows API, but it is bit harder :

    #include <windows.h>
    #include <userenv.h>
    ...
    HANDLE processToken = ::GetCurrentProcess();
    HANDLE user;
    BOOL cr = ::OpenProcessToken(processToken, TOKEN_ALL_ACCESS, &user);
    DWORD size = 2;
    char * buff = new char[size];
    cr = ::GetUserProfileDirectoryA(user, buff, &size); // find necessary size
    delete[] buff;
    buff = new char[size];
    cr = ::GetUserProfileDirectoryA(user, buff, &size);
    string profile = buff;
    delete[] buff;
    

    and you have to link with userenv.lib - the tests for return codes are left as an exercise :-)

  • via ExpandEnvironmentString :

    size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything",
        NULL, 2);
    buff = new char[size];
    size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything",
        buff, size);
    string profile = buff;
    delete[] buff;
    

With third way you have directly your string, with first and second you only get profile directory and still have to concatenate it with relevant path.

But in fact, if you want you program to be language independant, you should really use SHGetSpecialFolderPath API function :

    #include <shlobj.h>
    ...
    buff = new char[255];
    SHGetSpecialFolderPathA(HWND_DESKTOP, buff, CSIDL_DESKTOPDIRECTORY, FALSE);
    string desktop = buff;
    delete[] buff;

Because on my old XP box in french, Desktop is actually Bureau ...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • again why using raw new/delete and not using smart pointer or vector? this code is not exception safe – paulm Jan 04 '15 at 00:28