BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Patrick
Opal | Level 21

@Ksharp OH! It depends where you define the filename! If it's outside of the macro then the code won't get generated but if it's inside of the macro then the code will get generated. Have a play with below and you'll see.

Sooo... How would you redirect the log to "_null_" all done within the SAS macro? Is there any pre-defined libref we could use?

filename _null_ dummy;
%macro secure(val)/secure;
/*  filename _null_ dummy;*/
/*  data _null_;*/
/*    _rc=filename('_null_',,'dummy');*/
/*  run;*/

  proc printto log=_null_ new;
  run;
  data T;
    X="&val";
    putlog "This data step was generated from a secure macro with value &val..";
  run;
  proc print data=sashelp.class;
  run;
  proc printto;
  run;
%mend secure;

options MPRINT MLOGIC SYMBOLGEN SOURCE SOURCE2;
data _null_;
  infile datalines truncover;
  input val $;
  call execute(cats('%secure(',val,')'));
  datalines;
abc
;
Ksharp
Super User
Patrick,
I just take _null_ as
data _null_ ;
since there is not error in LOG , I think this should work.

But for your test code . the result same to me (a.k.a would not get sas code ).






103 filename _null_ dummy;
104 %macro secure(val)/secure;
105 /* filename _null_ dummy;*/
106 /* data _null_;*/
107 /* _rc=filename('_null_',,'dummy');*/
108 /* run;*/
109
110 proc printto log=_null_ new;
111 run;
112 data T;
113 X="&val";
114 putlog "This data step was generated from a secure macro with value &val..";
115 run;
116 proc print data=sashelp.class;
117 run;
118 proc printto;
119 run;
120 %mend secure;
121
122 options MPRINT MLOGIC SYMBOLGEN SOURCE SOURCE2;
123 data _null_;
124 infile datalines truncover;
125 input val $;
126 call execute(cats('%secure(',val,')'));
127 datalines;

NOTE: “DATA 语句”所用时间(总处理时间):
实际时间 0.01 秒
CPU 时间 0.00 秒


NOTE: CALL EXECUTE 生成了代码行。
129 ;
1 + proc printto log=_null_ new; run;

NOTE: “PROCEDURE PRINTTO”所用时间(总处理时间):
实际时间 0.00 秒
CPU 时间 0.00 秒


130 /*filename _null_ dummy;*/
131 %macro secure(val)/secure;
132 filename _null_ dummy;
133 data _null_;
134 _rc=filename('_null_',,'dummy');
135 run;
136
137 proc printto log=_null_ new;
138 run;
139 data T;
140 X="&val";
141 putlog "This data step was generated from a secure macro with value &val..";
142 run;
143 proc print data=sashelp.class;
144 run;
145 proc printto;
146 run;
147 %mend secure;
148
149 options MPRINT MLOGIC SYMBOLGEN SOURCE SOURCE2;
150 data _null_;
151 infile datalines truncover;
152 input val $;
153 call execute(cats('%secure(',val,')'));
154 datalines;

NOTE: “DATA 语句”所用时间(总处理时间):
实际时间 0.01 秒
CPU 时间 0.01 秒


NOTE: CALL EXECUTE 生成了代码行。
156 ;
1 + filename _null_ dummy;
1 + data _null_; _rc=filename('_null_',,'dummy'); run;

NOTE: “DATA 语句”所用时间(总处理时间):
实际时间 0.04 秒
CPU 时间 0.00 秒


1 + proc printto log=_null_ new; run;

NOTE: “PROCEDURE PRINTTO”所用时间(总处理时间):
实际时间 0.00 秒
CPU 时间 0.00 秒




















Patrick
Opal | Level 21

@Ksharp Strange. For below case with the filename within the macro my SAS log shows the generated SAS code.

 

/*filename _null_ dummy;*/
%macro secure(val)/secure;
  filename _null_ dummy;

  proc printto log=_null_ new;
  run;

  data T;
    X="&val";
    putlog "This data step was generated from a secure macro with value &val..";
  run;

  proc print data=sashelp.class;
  run;

  proc printto;
  run;

%mend secure;

options MPRINT MLOGIC SYMBOLGEN SOURCE SOURCE2;

data _null_;
  infile datalines truncover;
  input val $;
  call execute(cats('%secure(',val,')'));
  datalines;
abc
;
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      

NOTE: CALL EXECUTE generated line.
60         ;
1         + filename _null_ dummy;    data _null_;     _rc=filename('_null_',,'dummy');   run;    proc printto log=_null_ new;   
run;    data T;     X="abc";     putlog "This data step was generated from a secure macro with value abc.";   run;    proc print
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
3                                                          The SAS System                            23:34 Tuesday, October 12, 2021

 

Tom
Super User Tom
Super User

@Ksharp So you created a file named _null_.log in the current working directory.

962    proc printto log=_null_ new; run;

NOTE: PROCEDURE PRINTTO used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


965    data _null_;
966      infile '_null_.log';
967      input;
968      list;
969    run;

NOTE: The infile '_null_.log' is:
      Filename=c:\downloads\_null_.log,
      RECFM=V,LRECL=32767,File Size (bytes)=206,
      Last Modified=12Oct2021:19:28:21,
      Create Time=12Oct2021:19:27:25

RULE:     ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
1         NOTE: PROCEDURE PRINTTO used (Total process time): 50
2               real time           0.00 seconds 38
3               cpu time            0.00 seconds 38
4                6
5          0
6         963    %put hello; 18
7         hello 5
8         964    proc printto log=log; run; 33
9          0
NOTE: 9 records were read from the infile '_null_.log'.
      The minimum record length was 0.
      The maximum record length was 50.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
Ksharp
Super User
Tom,
Good eyes . impressed .
Quentin
Super User

Honestly, I was surprised that @Ksharp 's PROC PRINTTO worked (it worked when I tested it as well), as I thought the call execute timing wouldn't allow it to hide the code generated by the macro.  Curious in the environment where PROC PRINTTO alone doesn't work, does my DOSUBL approach with PROC PRINTTO running inside the DUSUBL block work?

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Patrick
Opal | Level 21

@Quentin Can't find a dosubl() example in this discussion but I've tried tons of options dosubl() included and could never make things work with everything defined within the macro only.

More than happy for you to give it a go.

Quentin
Super User

@Patrick  my suggestion relating to DOSUBL is (I think this link will work): https://communities.sas.com/t5/SAS-Programming/How-to-hide-SAS-macro-source-code/m-p/773394/highligh...

 

It worked for me, so I thought DOSUBL was helping with the timing (allowing the PROC PRINTTO to execute before the DATA step executes). But then @Ksharp 's dosubl-less PROC PRINTTO worked for me, so it's possible DOSUBL isn't helping.    Just curious what the result would be from that code in your environment, if the DOSUBL-less PROC PRINTTO isn't working for you there.

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Patrick
Opal | Level 21

@Quentin , @Ksharp , @ChrisNZ 

The silver bullet for Windows is destination nul. I wasn't aware that something like /dev/null exists under Windows. Learned something new and very useful 🙂

Already in my previous tests proc printto executed immediately IF the destination pre-existed. So now with nul that's the case and things just work even without dosubl(). 

/*filename _null_ dummy;*/
%macro secure(val)/secure;

  proc printto log="nul" new;
  run;

  data T;
    X="&val";
    putlog "This data step was generated from a secure macro with value &val..";
  run;

  proc print data=sashelp.class;
  run;

  proc printto;
  run;

%mend secure;

/*options MPRINT MLOGIC SYMBOLGEN SOURCE SOURCE2;*/

data _null_;
  infile datalines truncover;
  input val $;
  call execute(cats('%secure(',val,')'));
  datalines;
abc
;
NOTE: CALL EXECUTE generated line.
55         ;
1         + proc printto log="nul" new;   run;

 

ChrisNZ
Tourmaline | Level 20

It'd be useful that the null device existed to access the null device of the OS, so we don't have to test whether nul (DOS) or /dev/null (Unix) are to be used. Request created.

yabwon
Onyx | Level 15

You could replace the "temp" filename (which stores code in a file) with a "dummy" filename (which works like /dev/null).

 

 filename x DUMMY;
 proc printto log=x new;run;

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



yabwon
Onyx | Level 15

You could try to use the GSM package if you want, here is the doc: https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/gsm.md

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 42 replies
  • 4236 views
  • 32 likes
  • 10 in conversation