Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
1 View

call windows system command through fortran without showing the cmd window and output the result to an external file

Jump to solution

I'm doing a little project using fortran. A part of the code is designed to check the PC's mac address. Currently, I'm using call system command as follows:

 

CALL SYSTEM("ipconfig -all >result.tmp") 


Above code will invoke the windows ipconfig-all command and output the information to an external file result.tmp. Later this file will be read to check the mac address. 

Above works, except one annoying thing. The fortran code will be compiled as a dll and used by another C# program. The annoying thing is, whenever above code is executed in the C# program, a console window will be prompted shortly and then closed. I searched the forum to find if there is some way to disable the window prompt, it turns out there is some solution in the following link:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/506794?langu...

I tried that solution, it works fine for the system command "ipconfig -all", but I did not figure out how to output the result to an external file.  Does anyone can give me some hints on how to achieve that ?

Thanks

0 Kudos

Accepted Solutions
Highlighted
Valued Contributor I
1 View

Here is a module to access

Jump to solution

Here is a module to access MAC adapter info directly from Fortran, much easier than what you are doing now.

MODULE MAC  
    USE ifwinty  
    USE charfunc
    IMPLICIT NONE 
    PUBLIC GetMacInfo       !, PortExists
    PRIVATE
    SAVE
    
    INTEGER, PARAMETER :: MAX_ADAPTER_DESCRIPTION_LENGTH = 128  
    INTEGER, PARAMETER :: MAX_ADAPTER_NAME_LENGTH        = 256  
    INTEGER, PARAMETER :: MAX_ADAPTER_ADDRESS_LENGTH     =   8  
    INTEGER, PARAMETER :: MIB_IF_TYPE_ETHERNET           =   6  ! Ipifcons.h

    TYPE IP_ADDRESS_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_ADDRESS_STRING
     
    TYPE IP_MASK_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_MASK_STRING
      
    TYPE t_IP_ADDR_STRING   
        INTEGER (LPLONG)         :: pNext  
        TYPE (IP_ADDRESS_STRING) :: IpAddress  
        TYPE (IP_MASK_STRING)    :: IpMask  
        INTEGER (DWORD)          :: Context  
    END TYPE t_IP_ADDR_STRING
    
    TYPE t_IP_ADAPTER_INFO  
        INTEGER(LPLONG)         :: pNext   
        INTEGER(DWORD)          :: ComboIndex  
        CHARACTER(LEN=MAX_ADAPTER_NAME_LENGTH+4)        :: AdapterName  
        CHARACTER(LEN=MAX_ADAPTER_DESCRIPTION_LENGTH+4) :: Description  
        INTEGER(UINT)           :: AddressLength  
        INTEGER(BYTE)           :: Address(MAX_ADAPTER_ADDRESS_LENGTH)  
        INTEGER(DWORD)          :: Index  
        INTEGER(ULONG)          :: iType  
        INTEGER(ULONG)          :: DhcpEnabled  
        INTEGER(LPLONG)         :: pCurrentIpAddress   
        TYPE(t_IP_ADDR_STRING)  :: IpAddressList  
        TYPE(t_IP_ADDR_STRING)  :: GatewayList  
        TYPE(t_IP_ADDR_STRING)  :: DhcpServer  
        INTEGER(BOOL)           :: HaveWins  
        TYPE(t_IP_ADDR_STRING)  :: PrimaryWinsServer  
        TYPE(t_IP_ADDR_STRING)  :: SecondaryWinsServer  
        INTEGER(ULONG)          :: LeaseObtained  
        INTEGER(ULONG)          :: LeaseExpires  
    END TYPE t_IP_ADAPTER_INFO
     
    !   must link with IpHlpApi.lib to access this API function;
    !   this interface is not included in ifwinty
    INTERFACE  
        INTEGER(BOOL) FUNCTION GetAdaptersInfo (arg1, arg2)  
            USE ifwinty  
            !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetAdaptersInfo' :: GetAdaptersInfo  
            INTEGER(LPLONG) :: arg1  
            INTEGER(LPLONG) :: arg2  
        END FUNCTION  
    END INTERFACE
    
CONTAINS  
     
    
    SUBROUTINE GetMacInfo (hwnd, id)
        USE contwrap
        IMPLICIT NONE
        
        !   dialog window handle and set of static-text IDs for display
        INTEGER(HANDLE), INTENT(IN)         :: hwnd
        INTEGER, INTENT(IN), DIMENSION(4)   :: id 
            
        CHARACTER(LEN=200)                  :: msg
        INTEGER                             :: i, nc, count
        INTEGER, PARAMETER                  :: acount = 16
        TYPE(t_IP_ADAPTER_INFO),ALLOCATABLE :: ai(:)  
        
        count = 0
        
        !   allow for multiple adapters
        ALLOCATE (ai(acount))
        nc = SIZEOF(ai)
        IF (GetAdaptersInfo(LOC(ai), LOC(nc)) == 0) THEN  
            
            DO i = 1, acount
                SELECT CASE (ai(i)%iType)
                CASE (MIB_IF_TYPE_ETHERNET)
                    
                    !   line 1: description and MAC address
                    !nc = INDEX(ai(i)%Description, CHAR(0)) - 1
                    !WRITE (msg, '(A,",  ",5(Z2.2,"-"),Z2.2)') &
                    !    ai(i)%Description(1:nc),              &
                    !    ai(i)%Address(1:ai(i)%AddressLength)
                    nc = INDEX(ai(i)%Description, CHAR(0))
                    msg = ai(i)%Description(1:nc)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    !   line 2: IP and Gateway addresses
                    WRITE (msg, '("IP Addr: ",A,"  Gateway: ",A)')  &
                        ai(i)%IpAddressList%IpAddress%string,       &
                        ai(i)%GatewayList%IpAddress%string
                    CALL remove_nulls (msg)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    IF (count >= 4) EXIT
                END SELECT
                IF (ai(i)%pNext == NULL) EXIT  
            END DO
        
        END IF
        DEALLOCATE (ai)
    
    END SUBROUTINE GetMacInfo
         
END MODULE MAC  

 

View solution in original post

0 Kudos
9 Replies
Highlighted
Valued Contributor I
2 Views

Here is a module to access

Jump to solution

Here is a module to access MAC adapter info directly from Fortran, much easier than what you are doing now.

MODULE MAC  
    USE ifwinty  
    USE charfunc
    IMPLICIT NONE 
    PUBLIC GetMacInfo       !, PortExists
    PRIVATE
    SAVE
    
    INTEGER, PARAMETER :: MAX_ADAPTER_DESCRIPTION_LENGTH = 128  
    INTEGER, PARAMETER :: MAX_ADAPTER_NAME_LENGTH        = 256  
    INTEGER, PARAMETER :: MAX_ADAPTER_ADDRESS_LENGTH     =   8  
    INTEGER, PARAMETER :: MIB_IF_TYPE_ETHERNET           =   6  ! Ipifcons.h

    TYPE IP_ADDRESS_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_ADDRESS_STRING
     
    TYPE IP_MASK_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_MASK_STRING
      
    TYPE t_IP_ADDR_STRING   
        INTEGER (LPLONG)         :: pNext  
        TYPE (IP_ADDRESS_STRING) :: IpAddress  
        TYPE (IP_MASK_STRING)    :: IpMask  
        INTEGER (DWORD)          :: Context  
    END TYPE t_IP_ADDR_STRING
    
    TYPE t_IP_ADAPTER_INFO  
        INTEGER(LPLONG)         :: pNext   
        INTEGER(DWORD)          :: ComboIndex  
        CHARACTER(LEN=MAX_ADAPTER_NAME_LENGTH+4)        :: AdapterName  
        CHARACTER(LEN=MAX_ADAPTER_DESCRIPTION_LENGTH+4) :: Description  
        INTEGER(UINT)           :: AddressLength  
        INTEGER(BYTE)           :: Address(MAX_ADAPTER_ADDRESS_LENGTH)  
        INTEGER(DWORD)          :: Index  
        INTEGER(ULONG)          :: iType  
        INTEGER(ULONG)          :: DhcpEnabled  
        INTEGER(LPLONG)         :: pCurrentIpAddress   
        TYPE(t_IP_ADDR_STRING)  :: IpAddressList  
        TYPE(t_IP_ADDR_STRING)  :: GatewayList  
        TYPE(t_IP_ADDR_STRING)  :: DhcpServer  
        INTEGER(BOOL)           :: HaveWins  
        TYPE(t_IP_ADDR_STRING)  :: PrimaryWinsServer  
        TYPE(t_IP_ADDR_STRING)  :: SecondaryWinsServer  
        INTEGER(ULONG)          :: LeaseObtained  
        INTEGER(ULONG)          :: LeaseExpires  
    END TYPE t_IP_ADAPTER_INFO
     
    !   must link with IpHlpApi.lib to access this API function;
    !   this interface is not included in ifwinty
    INTERFACE  
        INTEGER(BOOL) FUNCTION GetAdaptersInfo (arg1, arg2)  
            USE ifwinty  
            !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetAdaptersInfo' :: GetAdaptersInfo  
            INTEGER(LPLONG) :: arg1  
            INTEGER(LPLONG) :: arg2  
        END FUNCTION  
    END INTERFACE
    
CONTAINS  
     
    
    SUBROUTINE GetMacInfo (hwnd, id)
        USE contwrap
        IMPLICIT NONE
        
        !   dialog window handle and set of static-text IDs for display
        INTEGER(HANDLE), INTENT(IN)         :: hwnd
        INTEGER, INTENT(IN), DIMENSION(4)   :: id 
            
        CHARACTER(LEN=200)                  :: msg
        INTEGER                             :: i, nc, count
        INTEGER, PARAMETER                  :: acount = 16
        TYPE(t_IP_ADAPTER_INFO),ALLOCATABLE :: ai(:)  
        
        count = 0
        
        !   allow for multiple adapters
        ALLOCATE (ai(acount))
        nc = SIZEOF(ai)
        IF (GetAdaptersInfo(LOC(ai), LOC(nc)) == 0) THEN  
            
            DO i = 1, acount
                SELECT CASE (ai(i)%iType)
                CASE (MIB_IF_TYPE_ETHERNET)
                    
                    !   line 1: description and MAC address
                    !nc = INDEX(ai(i)%Description, CHAR(0)) - 1
                    !WRITE (msg, '(A,",  ",5(Z2.2,"-"),Z2.2)') &
                    !    ai(i)%Description(1:nc),              &
                    !    ai(i)%Address(1:ai(i)%AddressLength)
                    nc = INDEX(ai(i)%Description, CHAR(0))
                    msg = ai(i)%Description(1:nc)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    !   line 2: IP and Gateway addresses
                    WRITE (msg, '("IP Addr: ",A,"  Gateway: ",A)')  &
                        ai(i)%IpAddressList%IpAddress%string,       &
                        ai(i)%GatewayList%IpAddress%string
                    CALL remove_nulls (msg)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    IF (count >= 4) EXIT
                END SELECT
                IF (ai(i)%pNext == NULL) EXIT  
            END DO
        
        END IF
        DEALLOCATE (ai)
    
    END SUBROUTINE GetMacInfo
         
END MODULE MAC  

 

View solution in original post

0 Kudos
Highlighted
Black Belt
1 View

I agree with Paul that the

Jump to solution

I agree with Paul that the Windows API is the way to go. For your general question, the problem is that SYSTEM doesn't execute a shell command, so you can't do redirection. I looked at ShellExecute, but it too doesn't support redirection. You'd probably have to go to CreateProcess and specify a file handle as standard output.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Valued Contributor II
1 View

Actually, if you need

Jump to solution

Actually, if you need redirection, then using the routine execute_command_line will do exactly what you want:
 

program run_command
    implicit none

    call execute_command_line( "ipconfig -all > cmd.out" )
end program run_command

 

0 Kudos
Highlighted
Beginner
1 View

Quote:Paul Curtis wrote:

Jump to solution

Paul Curtis wrote:

Here is a module to access MAC adapter info directly from Fortran, much easier than what you are doing now.

MODULE MAC  
    USE ifwinty  
    USE charfunc
    IMPLICIT NONE 
    PUBLIC GetMacInfo       !, PortExists
    PRIVATE
    SAVE
    
    INTEGER, PARAMETER :: MAX_ADAPTER_DESCRIPTION_LENGTH = 128  
    INTEGER, PARAMETER :: MAX_ADAPTER_NAME_LENGTH        = 256  
    INTEGER, PARAMETER :: MAX_ADAPTER_ADDRESS_LENGTH     =   8  
    INTEGER, PARAMETER :: MIB_IF_TYPE_ETHERNET           =   6  ! Ipifcons.h

    TYPE IP_ADDRESS_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_ADDRESS_STRING
     
    TYPE IP_MASK_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_MASK_STRING
      
    TYPE t_IP_ADDR_STRING   
        INTEGER (LPLONG)         :: pNext  
        TYPE (IP_ADDRESS_STRING) :: IpAddress  
        TYPE (IP_MASK_STRING)    :: IpMask  
        INTEGER (DWORD)          :: Context  
    END TYPE t_IP_ADDR_STRING
    
    TYPE t_IP_ADAPTER_INFO  
        INTEGER(LPLONG)         :: pNext   
        INTEGER(DWORD)          :: ComboIndex  
        CHARACTER(LEN=MAX_ADAPTER_NAME_LENGTH+4)        :: AdapterName  
        CHARACTER(LEN=MAX_ADAPTER_DESCRIPTION_LENGTH+4) :: Description  
        INTEGER(UINT)           :: AddressLength  
        INTEGER(BYTE)           :: Address(MAX_ADAPTER_ADDRESS_LENGTH)  
        INTEGER(DWORD)          :: Index  
        INTEGER(ULONG)          :: iType  
        INTEGER(ULONG)          :: DhcpEnabled  
        INTEGER(LPLONG)         :: pCurrentIpAddress   
        TYPE(t_IP_ADDR_STRING)  :: IpAddressList  
        TYPE(t_IP_ADDR_STRING)  :: GatewayList  
        TYPE(t_IP_ADDR_STRING)  :: DhcpServer  
        INTEGER(BOOL)           :: HaveWins  
        TYPE(t_IP_ADDR_STRING)  :: PrimaryWinsServer  
        TYPE(t_IP_ADDR_STRING)  :: SecondaryWinsServer  
        INTEGER(ULONG)          :: LeaseObtained  
        INTEGER(ULONG)          :: LeaseExpires  
    END TYPE t_IP_ADAPTER_INFO
     
    !   must link with IpHlpApi.lib to access this API function;
    !   this interface is not included in ifwinty
    INTERFACE  
        INTEGER(BOOL) FUNCTION GetAdaptersInfo (arg1, arg2)  
            USE ifwinty  
            !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetAdaptersInfo' :: GetAdaptersInfo  
            INTEGER(LPLONG) :: arg1  
            INTEGER(LPLONG) :: arg2  
        END FUNCTION  
    END INTERFACE
    
CONTAINS  
     
    
    SUBROUTINE GetMacInfo (hwnd, id)
        USE contwrap
        IMPLICIT NONE
        
        !   dialog window handle and set of static-text IDs for display
        INTEGER(HANDLE), INTENT(IN)         :: hwnd
        INTEGER, INTENT(IN), DIMENSION(4)   :: id 
            
        CHARACTER(LEN=200)                  :: msg
        INTEGER                             :: i, nc, count
        INTEGER, PARAMETER                  :: acount = 16
        TYPE(t_IP_ADAPTER_INFO),ALLOCATABLE :: ai(:)  
        
        count = 0
        
        !   allow for multiple adapters
        ALLOCATE (ai(acount))
        nc = SIZEOF(ai)
        IF (GetAdaptersInfo(LOC(ai), LOC(nc)) == 0) THEN  
            
            DO i = 1, acount
                SELECT CASE (ai(i)%iType)
                CASE (MIB_IF_TYPE_ETHERNET)
                    
                    !   line 1: description and MAC address
                    !nc = INDEX(ai(i)%Description, CHAR(0)) - 1
                    !WRITE (msg, '(A,",  ",5(Z2.2,"-"),Z2.2)') &
                    !    ai(i)%Description(1:nc),              &
                    !    ai(i)%Address(1:ai(i)%AddressLength)
                    nc = INDEX(ai(i)%Description, CHAR(0))
                    msg = ai(i)%Description(1:nc)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    !   line 2: IP and Gateway addresses
                    WRITE (msg, '("IP Addr: ",A,"  Gateway: ",A)')  &
                        ai(i)%IpAddressList%IpAddress%string,       &
                        ai(i)%GatewayList%IpAddress%string
                    CALL remove_nulls (msg)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    IF (count >= 4) EXIT
                END SELECT
                IF (ai(i)%pNext == NULL) EXIT  
            END DO
        
        END IF
        DEALLOCATE (ai)
    
    END SUBROUTINE GetMacInfo
         
END MODULE MAC  

 

 

Thank you for your suggestion Paul!. I've made a try, but the compiler reported an error, saying that Check include path for [CHARFUNC] and [ifwinty]. Besides, in your provided sample code, it is said "IpHlpApi.lib must be linked", Unfortunately, I searched the library file but it returns nothing. There is a IpHlpApi.dll located under windows/system32 though.  I'm not quite familiar with fortran coding, will you give me some hints how to run your code? Truly appreciated for your help.

0 Kudos
Highlighted
Beginner
1 View

Quote:Arjen Markus wrote:

Jump to solution

Arjen Markus wrote:

Actually, if you need redirection, then using the routine execute_command_line will do exactly what you want:
 

program run_command
    implicit none

    call execute_command_line( "ipconfig -all > cmd.out" )
end program run_command

 

 

Thanks for your suggestion. Unfortunately I'm using IVF, which does not support the command execute_command_line yet

0 Kudos
Highlighted
Valued Contributor II
1 View

Which version? The routine is

Jump to solution

Which version? The routine is a standard routine in Fortran 2008. It was already available in IVF 2017. A workaround might be to put the ipconfig command with the redirection in a batch file (perhaps written on the fly). Not very elegant and you may need to specify the command as: "cmd /c name-of-batch.bat", but it ought to work ;).

0 Kudos
Highlighted
Black Belt
1 View

You can see from the release

Jump to solution

You can see from the release notes for IFort 16.0 that EXECUTE_COMMAND_LINE was added in that version:

     https://software.intel.com/en-us/articles/intel-visual-fortran-compiler-160-for-windows-release-notes-for-intel-parallel-studio-xe#f08_f15

 

0 Kudos
Highlighted
Beginner
1 View

Quote:Arjen Markus wrote:

Jump to solution

Arjen Markus wrote:

Which version? The routine is a standard routine in Fortran 2008. It was already available in IVF 2017. A workaround might be to put the ipconfig command with the redirection in a batch file (perhaps written on the fly). Not very elegant and you may need to specify the command as: "cmd /c name-of-batch.bat", but it ought to work ;).

I'm still using IVF 2013 -_-! Maybe I should update to IVF 2017 in future

0 Kudos
Highlighted
Valued Contributor I
1 View

My module was extracted from

Jump to solution

My module was extracted from a larger program in which the recovered MAC info text was passed to a dialog for display.  You can ignore (ie, delete) the reference to charfunc, and deal with the MAC strings however you want (ie, perhaps as returned args).  I have attached IPHlpApi.lib as a zipfile.

 

0 Kudos