Macro to find my documents folder

efortin's icon

Does anyone know of a way to find the my documents folder for the current user windows operating systems? The user needs to be able to read and write a temp file to a directory. This needs directory needs to be available to all users or needs to be available to the current user like the "My documents" folder. Any ideas on how to find this folder dynamically?

Johannes's icon

Hi,

I wrote an external for Windows which you can use to ask for the environment variables. One of them should be the userprofile

Here is a link to a snippet how to read out all environment variables in c

#include "ext.h"                            // standard Max include, always required
#include "ext_obex.h"                        // required for new style Max object
#include  //Needed for getenv()
#include  //Needed for strings

////////////////////////// object struct
typedef struct _commonprogramfiles
{
    t_object    ob;
    t_atom        val;
    t_symbol    *name;
    void        *out;
} t_commonprogramfiles;

///////////////////////// function prototypes
//// standard set
void *commonprogramfiles_new(t_symbol *s, long argc, t_atom *argv);
void commonprogramfiles_free(t_commonprogramfiles *x);
void commonprogramfiles_assist(t_commonprogramfiles *x, void *b, long m, long a, char *s);

void commonprogramfiles_int(t_commonprogramfiles *x, long n);
void commonprogramfiles_float(t_commonprogramfiles *x, double f);
void commonprogramfiles_anything(t_commonprogramfiles *x, t_symbol *s, long ac, t_atom *av);
void commonprogramfiles_bang(t_commonprogramfiles *x);
void commonprogramfiles_identify(t_commonprogramfiles *x);
void commonprogramfiles_dblclick(t_commonprogramfiles *x);
void commonprogramfiles_acant(t_commonprogramfiles *x);
void commonprogramfiles_getenv(t_commonprogramfiles *x, t_symbol *myEnv);

//////////////////////// global class pointer variable
void *commonprogramfiles_class;

int main(void)
{
    t_class *c;

    c = class_new("commonprogramfiles", (method)commonprogramfiles_new, (method)commonprogramfiles_free, (long)sizeof(t_commonprogramfiles),
                  0L /* leave NULL!! */, A_GIMME, 0);

    class_addmethod(c, (method)commonprogramfiles_bang,            "bang", 0);
    class_addmethod(c, (method)commonprogramfiles_int,            "int",        A_LONG, 0);
    class_addmethod(c, (method)commonprogramfiles_float,            "float",    A_FLOAT, 0);
    class_addmethod(c, (method)commonprogramfiles_anything,        "anything",    A_GIMME, 0);
    class_addmethod(c, (method)commonprogramfiles_identify,        "identify", 0);
    CLASS_METHOD_ATTR_PARSE(c, "identify", "undocumented", gensym("long"), 0, "1");

    // we want to 'reveal' the otherwise hidden 'xyzzy' method
    class_addmethod(c, (method)commonprogramfiles_anything,        "xyzzy", A_GIMME, 0);
    // here's an otherwise undocumented method, which does something that the user can't actually
    // do from the patcher however, we want them to know about it for some weird documentation reason.
    // so let's make it documentable. it won't appear in the quickref, because we can't send it from a message.
    class_addmethod(c, (method)commonprogramfiles_acant,            "blooop", A_CANT, 0);
    CLASS_METHOD_ATTR_PARSE(c, "blooop", "documentable", gensym("long"), 0, "1");

    /* you CAN'T call this from the patcher */
    class_addmethod(c, (method)commonprogramfiles_assist,            "assist",        A_CANT, 0);
    class_addmethod(c, (method)commonprogramfiles_dblclick,            "dblclick",        A_CANT, 0);
    class_addmethod(c, (method)commonprogramfiles_getenv,            "getenv", A_SYM, 0);

    CLASS_ATTR_SYM(c, "name", 0, t_commonprogramfiles, name);

    class_register(CLASS_BOX, c);
    commonprogramfiles_class = c;

    return 0;
}

void commonprogramfiles_acant(t_commonprogramfiles *x)
{
    object_post((t_object *)x, "can't touch this!");
}

void commonprogramfiles_assist(t_commonprogramfiles *x, void *b, long m, long a, char *s)
{
    if (m == ASSIST_INLET) { //inlet
        sprintf(s, "I am inlet %ld", a);
    }
    else {    // outlet
        sprintf(s, "I am outlet %ld", a);
    }
}

void commonprogramfiles_free(t_commonprogramfiles *x)
{
    ;
}

void commonprogramfiles_dblclick(t_commonprogramfiles *x)
{
    object_post((t_object *)x, "I got a double-click");
}

void commonprogramfiles_int(t_commonprogramfiles *x, long n)
{
    atom_setlong(&x->val, n);
    commonprogramfiles_bang(x);
}

void commonprogramfiles_float(t_commonprogramfiles *x, double f)
{
    atom_setfloat(&x->val, f);
    commonprogramfiles_bang(x);
}

void commonprogramfiles_anything(t_commonprogramfiles *x, t_symbol *s, long ac, t_atom *av)
{
    if (s == gensym("xyzzy")) {
        object_post((t_object *)x, "A hollow voice says 'Plugh'");
    } else {
        atom_setsym(&x->val, s);
        commonprogramfiles_bang(x);
    }
}

void commonprogramfiles_bang(t_commonprogramfiles *x)
{
    switch (x->val.a_type) {
        case A_LONG: outlet_int(x->out, atom_getlong(&x->val)); break;
        case A_FLOAT: outlet_float(x->out, atom_getfloat(&x->val)); break;
        case A_SYM: outlet_anything(x->out, atom_getsym(&x->val), 0, NULL); break;
        default: break;
    }
}

void commonprogramfiles_identify(t_commonprogramfiles *x)
{
    object_post((t_object *)x, "my name is %s", x->name->s_name);
}

void *commonprogramfiles_new(t_symbol *s, long argc, t_atom *argv)
{
    t_commonprogramfiles *x = NULL;

    if (x = (t_commonprogramfiles *)object_alloc(commonprogramfiles_class)) {
        x->name = gensym("");
        if (argc && argv) {
            x->name = atom_getsym(argv);
        }
        if (!x->name || x->name == gensym(""))
            x->name = symbol_unique();

        atom_setlong(&x->val, 0);
        x->out = outlet_new(x, NULL);
    }
    return (x);
}

void commonprogramfiles_getenv(t_commonprogramfiles *x, t_symbol *myEnv)
{
    t_symbol bla;
    char toConform[1024];
    bla.s_name = getenv(myEnv->s_name);
    path_nameconform(bla.s_name, toConform, PATH_STYLE_SLASH, PATH_TYPE_ABSOLUTE);
    outlet_anything(x->out, gensym(toConform), 0, NULL);
}
Johannes's icon

Hi again,

missed the mostimportant thing. After you created the external you can use it sending a message "getenv " to it.

Best,
Johannes