Tuesday, September 30, 2014

FoxPro form flashes on the screen and disappeares

I am working on my first Visual Foxpro program. My program was not waiting for any event and just closed immediately. I could not figure out the reason until I found this article.

http://www.alvechurchdata.co.uk/company/foxflash.html

FoxPro form flashes on the screen and vanishes

Everybody meets this problem with their first Visual FoxPro executable; the program runs well in the development environment but fails when run as a stand-alone executable from Windows. The FoxPro window just flashes on the screen and then vanishes. You can search VFP Help for terms like "flash", "vanish" and "disappear" but you will find nothing. The information is hidden away under "How to: Control the Event Loop" and you won't be able to ship your exe until you find it.
This problem crops up because Visual FoxPro is now an event-driven language. It runs through the code for your form, reaches the end, and the program terminates when there is nothing more for it to do. Everything vanishes from the screen. The same thing will happen if your application is based on a main menu; FoxPro will run through the code to create the menu, the menu will flash on the screen but then the program terminates and the menu vanishes.
The solution is a simple one once you realise what FoxPro is doing. You have to tell VFP to start its event-processing loops. The command that does this is:
Read Events
You'll need to add this code in different places depending on whether you are using a form, a menu or a program as the main element of your application.
If you are using a form then add this as the last line in the Activate event. This will allow the form to load and initialise itself before going into the event processing loop and waiting for mouse and keyboard events.
In a menu, add it to the CleanUp code snippet. Select General Options from the View menu then click the Cleanup... tick box. An edit window will open behind the dialog; click OK to close the dialog window and the CleanUp edit window will remain:
[VFP Edit window for menu cleanup code]
If you have a program as the main element of your project then add the Read Events line immediately after you have set up the user interface by loading a form or menu. Fox will then stop executing this sequential code and will start monitoring keyboard and mouse events, waiting to see what it should do next.

One last thing to remember

[Cannot Quit Visual FoxPro message] This will start the event processing loop but we need to stop the loop in order to close the application. If you forget to do this then you'll hit the second most-common problem - the "Cannot quit Visual FoxPro." message.
You avoid this by using the Clear Events command to stop the event-processing loop. Execution will then continue from the line following the Read Events command in the main program.
Read more details on being unable to quit FoxPro here.

Friday, April 25, 2014

Windows Script Host


Microsoft Windows Script Host (WSH) is a language-independent scripting host for Windows Script compatible scripting engines. It brings simple, powerful, and flexible scripting to the Windows 32-bit platform, allowing you to run scripts from both the Windows desktop and the command prompt.

Using Windows Scripting Host, VBScript performed tasks that the Windows shell (batch scripts) simply could not handle. Windows Script Host is ideal for non-interactive scripting needs, such as logon scripting, administrative scripting, and machine automation.

This is the link for Windows Script Host
http://msdn.microsoft.com/en-us/library/9bbdkx3k(v=vs.84).aspx


In VBScript, we can create Windows Script Host (WSH) Objects and automate manual tasks.

These are the 14 WSH Objects:

Scripting.Signer Object  
Enables an author to sign a script with a digital signature and a recipient to verify the signature's authenticity and trustworthiness.

WScript Object 
Provides access to most of the objects, methods, and properties in the WSH object model.

WshArguments Object
 Gives you access to the entire collection of command-line parameters — in the order in which they were originally entered.

WshController Object
 Exposes the method CreateScript() that creates a remote script process.

WshEnvironment Object
 Gives you access to the collection of Microsoft Windows system environment variables.

WshNamed Object
 Provides access to the named command-line script arguments within the WshArguments object.

WshNetwork Object
 Gives you access to the shared resources on the network to which your computer is connected.

WshRemote Object
 Provides access to the remote script process.

WshRemoteError Object
 Exposes the error information available when a remote script (a WshRemote object) terminates as a result of a script error.

WshScriptExec Object
 Provides status and error information about a script run with Exec, along with access to the stdIn, stdOut, and stdErr channels.

WshShell Object
 Gives you access to the native Windows shell functionality.

WshShortcut Object
 Allows you to create a shortcut programmatically.

WshSpecialFolders Object
 Allows you to access the Windows Special Folders.

WshUnnamed Object
 Provides access to the unnamed command-line script arguments within the WshArguments object.

WshUrlShortcut Object
 Allows you to create a shortcut to an Internet resource, programmatically.
 
Link: http://msdn.microsoft.com/en-us/library/a74hyyw0(v=vs.84).aspx


This is the reference page:
http://msdn.microsoft.com/en-us/library/98591fh7(v=vs.84).aspx


Wednesday, April 2, 2014

Script to load program in administrator elevated mode

One of our users needs to run a program in elevated mode. I added her in the local admin group, but she still have to right click the shortcut and select "Run as Administrator" and then click OK in the pop up UAC window. The user complained about all the clicks.

I googled it and found this script to avoid all these steps. User just double click the shortcut to the batch file and the batch file runs the program in elevated mode.


https://sites.google.com/site/eneerge/scripts/batchgotadmin

Basically this just creates a VBS Script on the fly and invokes the batch script using it. It checks to see if the current window is running as administrator by attempting to create a folder that requires administrative access. If the directory can not be created, then it invokes the UAC dialog, then closes the non-admin window. The script can also be executed from an already open administrative CLI.
 
 
========== Batch file: RunProgram.bat =================================

@echo off

:------------------------:
: BatchGotAdmin     :
:------------------------:

REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )


:UACPrompt

    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", "", "", "runas", 1  >> "%temp%\getadmin.vbs"
    "%temp%\getadmin.vbs"
    exit /B

:gotAdmin

    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"

:--------------------------------------
REM  creat a temp batch file to run the real program
    
echo net use p: /delete /y >%temp%\runProgram-temp.bat
echo net use p: "\\Server1\program files" >>%temp%\runProgram-temp.bat
echo net use n: /delete /y >>%temp%\runProgram-temp.bat
echo net use n: \\Server1\groups >>%temp%\runProgram-temp.bat
echo p:\myProgram\myProgram.exe >>%temp%\runProgram-temp.bat
echo exit >>%temp%\runProgram-temp.bat
start /min %temp%\runProgram-temp.bat

======================= End of Batch file =======================

Friday, November 1, 2013

Powershell script to check domain password policy and user password status.

One of our domain users tried to change his password and he got the error message:
"Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirements of the domain."

I tried to find the reason. Many people mentioned that the problem might be the setting of "Min password age", then I found this Power Shell scipt which can give me the setting of password policy and the last time user changed his password.

This is the original link:
http://www.blackops.ca/cms/blog/?p=295

This is the scipt code:
===========================

cls
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
While (!$result){
  $UserName = Read-Host 'Username to check : '
  if (!$UserName){
    Write-Host "No Username Entered"exit
  }
  $searcher.Filter = "(&(objectClass=User)(samAccountName=" + $username + "))"
  $result = $searcher.Findone()
}
# get domain password policy (max pw age)
$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Domain = [ADSI]"LDAP://$D"
$MPA = $Domain.maxPwdAge.Value
$MinPA = $Domain.minPwdAge.Value
# Convert to Int64 ticks (100-nanosecond intervals).
$lngMaxPwdAge = $Domain.ConvertLargeIntegerToInt64($MPA)
$lngMinPwdAge = $Domain.ConvertLargeIntegerToInt64($MinPA)
$MinPwdLength = $Domain.minPwdLength
$PwdHistory = $Domain.pwdHistoryLength
# Convert to days.
$MaxPwdAge = -$lngMaxPwdAge/(600000000 * 1440)
$MinPwdAge = -$lngMinPwdAge/(600000000 * 1440)
$lngPwdLastSet =$result.Properties.pwdlastset
$pwdLastSet = [datetime]::FromFileTime($lngPwdLastSet[0])
Write-Host $result.Path
Write-Host $result.Properties.cn " " $result.Properties.userprincipalname
Write-Host "Password Last Set : " $pwdLastSet
Write-Host "Max Password Age : " $MaxPwdAge
Write-Host "Min Password Age : " $MinPwdAge
Write-Host "Password History : " $PwdHistory
Write-Host "Min Password Length : " $MinPwdLength
if ($pwdLastSet -ge (Get-Date).AddDays(-$MinPwdAge)){
  Write-Host -ForegroundColor Red "Password can not be changed - Min Age"
}
if ($pwdLastSet -ge (Get-Date).AddDays($MaxPwdAge)){
  Write-Host -ForegroundColor Red "Password Expired"
}

========== end of scipt =====================

Thursday, July 25, 2013

Active Directory Service Interfaces

Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the features of directory services from different network providers. ADSI is used in a distributed computing environment to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, no matter which network environment contains the resource.

ADSI enables common administrative tasks, such as adding new users, managing printers, and locating resources in a distributed computing environment.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772170(v=vs.85).aspx

Active Directory Service Interfaces Reference
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772218(v=vs.85).aspx

=============================================================

We can use System Providers in ADSI to create object and remotely manage Active Directory.  ADSI includes the service providers listed in this page:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772235(v=vs.85).aspx


Example:

For ADSI WinNT Provider

We can use Set objUser = GetObject("WinNT://"& strDomain &"/" & strUser) to create an IADsUser object and access the IADsUser object properties.

This page has all the objects of WINNT provider
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772211(v=vs.85).aspx

IADsUser is one of the WINNT objects. This page has the interface of IADsUser, including methods and properties.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa746340(v=vs.85).aspx

This method can set user password: objUser.SetPassword strPassword

Tuesday, July 23, 2013

Remotely access Exchange 2010 with PowerShell Script

Remotely check Exchange 2010 mailbox size

'Run these two commands in PowerShell first to remotely connect to exchange server from local PowerShell

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://(server name)/PowerShell/ -Authentication Kerberos

Import-PSSession $Session


'Do query

'Get one user mailbox size, can also get subfolder size by changing -folder value
Get-MailboxStatistics -Identity UserName | select -Property TotalItemSize


'This can also give the mailbox size
Get-MailboxFolderStatistics -Identity UserName -folderscope all | select -Property FolderAndSubfolderSize -first 1


'Get mailboxe size for all mailboxes
Get-MailboxStatistics -server myExchangeServerName | select Displayname,TotalItemSize | Sort-Object Displayname


'Export result to Excel file
Get-MailboxStatistics -server myExchangeServerName | select Displayname,TotalItemSize | Sort-Object Displayname | Export-CSV c:\temp\inboxsizes.csv


'View all quotas assigned to a mailbox
Get-Mailbox UserName | Format-List *Quota


'export result to Excel file
Get-MailboxStatistics -server mfl67207 | select Displayname,TotalItemSize | Sort-Object Displayname | Export-CSV c:\temp\inboxsizes.csv



'View all quotas assigned to a mailbox
Get-Mailbox <Identity> | Format-List *Quota



'Exporting Message Tracking Logs to .CSV
Get-MessageTrackingLog -Server <Server name> -Start "01/01/13 00:00:00" -End "12/12/13 23:59:59" -Recipient "TheMole@BadGuyCompany.com" -Resultsize unlimited| select sender, recipient, timestamp, messagesubject, totalbytes | export-csv c:\temp\messlog.csv


'Check inbox rule
Get-InboxRule –Mailbox <username> | fl > \temp\outlookClientRules.txt


'Disable a users Outlook Rules
Disable-Inboxrule –Mailbox <Bob Smith> -Identity “<TheOutlookRule>”




'To delete a specific users Outlook Rules
Remove-Inboxrule –Mailbox <Bob Smith> -Identity “<TheOutlookRule>”


'This is a link for Powershell command Get-mailboxstatistics
http://technet.microsoft.com/en-us/library/bb124612(v=exchg.150).aspx


'I found the above command from this page:
http://help.outlook.com/en-us/140/Gg576861.aspx


'This is Microsoft page about Powershell cmdlet
https://technet.microsoft.com/en-us/library/bb123981(v=exchg.160).aspx

Thursday, June 20, 2013

VBScript to manage user accounts

VBscript can use WMI object to access properties of Domain and users.

===============================================
Unlock User Account
-------------------------------------------------------------------------------
This is a sample code to unlock user account when user put wrong password too many times and his account has been locked.

Code 1:

Dim oUser
Set oUser = GetObject("WinNT://DomainName/UserName")
WScript.Echo "user name:" & oUser.Name&vbcr&"Is account locked:" & oUser.IsAccountLocked
oUser.IsAccountLocked = 0
WScript.Echo "user name:" & oUser.Name&vbcr&"Is account locked:" & oUser.IsAccountLocked

A better pice of code can be found here:
http://community.spiceworks.com/scripts/show/54-unlock-user-account

Code 2:

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

objUser.IsAccountLocked = False
oUser.SetInfo

===================================================
Reset User Account Password
-------------------------------------------------------------------------------
This is a sample code to reset user account password.

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

strPassword = InputBox("Please put a new password.","Reset User password")
oUser.SetPassword strPassword
oUser.SetInfo

===================================================
Force User to Change Account Password at The First Login
-------------------------------------------------------------------------------
This is a sample code to reset user account password.

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

objUser.PwdLastSet = 0
oUser.SetInfo
===================================================

Find LDAP distinguished name (DN) in AD
-------------------------------------------------------------------------------

I found this script code on Microsoft website.

http://gallery.technet.microsoft.com/scriptcenter/dee78632-f6d0-4be3-920f-27165fa60767

'**************************************************************
'=  Created By: Devin H.
'=  Function Name: distinguish           Date: 10/19/2005           Version:1.1
'=  
'=  Variables: strObject, strType  
'= 
'=  This function will return the distinguished name of an object stored in 
'=  Active Directory.  This is useful when you don't know exactly where an 
'=  object is located or want to move something.
'=  
'=  Usage: Wscript.Echo distinguish("DevinH","user") 
'=  Returns: cn=DevinH,ou=MyUsers,dc=ScriptCentric,dc=com       
'=
'**************************************************************
Function distinguish(strObject, strType)
    Select case strType
        Case lcase("computer")
            strobject = strObject & "$"
        Case lcase("user")
            'Good
        Case lcase("group")
            'Good
        Case else
            Wscript.Echo "Their is an error in the script"
    End Select
    ' Determine DNS domain name (this could be hard coded).
    Set objRootDSE = getObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.get("defaultNamingContext")
    
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = createObject("ADODB.Connection")
    Set objCommand = createObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    
    Set objCOmmand.ActiveConnection = objConnection
    objCommand.CommandText = _
    "Select distinguishedname, Name, Location from 'LDAP://" & strDNSDomain & _
    "' Where objectClass='" & strType & "' and samaccountname='" & strobject & "'"
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    Set objRecordSet = objCommand.execute
    objRecordSet.MoveFirst
    
    Do Until objRecordSet.EOF
       distinguish = objRecordSet.Fields("distinguishedname")
       objRecordSet.MoveNext
    Loop
End Function

===================================================

This is my code with all these together

'*********** code begin*****************

On Error Resume Next
strUser = InputBox("Please enter a user name.","user_password")
If strUser = vbNullString then
   MsgBox "Either Cancel was selected or you did not enter a user name.", 16, "User Unlock"
   WScript.Quit
End If
strDomain = "myDOMAIN"
dim LDAPpath
Const STRING_OBJ_TYPE = "user"
LDAPpath = distinguish(strUser,STRING_OBJ_TYPE)
Set objUser = GetObject("LDAP://" & LDAPpath)
If Err.Number <> 0 Then
   MsgBox (strUser) & " isn't a valid user name!", 48,"Reset User password"
   Wscript.Quit
End If
Err.Clear
On Error Resume Next
   style = vbYesNo + vbDefaultButton2
    
   'set new password  
   WantNewPwd = MsgBox("Do you want to reset user's password?", style,"user_password")
   If WantNewPwd = vbYes Then
       strPassword = InputBox("Please put a new password.","Reset User password")
       objUser.SetPassword strPassword
   End If
  
   'force user to change the password at the first time login
   forceNewPsd = MsgBox("Do you want user to change password at first login?", style,"user_password")
   If forceNewPsd = vbYes Then
       objUser.PwdLastSet = 0
   End If
   UnlockAccount = MsgBox("Do you want to unlock user account?", style,"user_password")
   If UnlockAccount = vbYes Then
       objUser.IsAccountLocked = False
   End If 
  
   objUser.SetInfo
If Err.Number <> 0 Then
   MsgBox("An error has occurred. " & Err.Number)
   Err.Clear
Else
   MsgBox "The Password/Account Has Been Changed For " & UCase(strDomain) & "\" & UCase(strUser)
End If
Wscript.Quit

'=====================================================
'=  Created By: Devin H.
'=  Function Name: distinguish           Date: 10/19/2005           Version:1.1
'=  
'=  Variables: strObject, strType  
'= 
'=  This function will return the distinguished name of an object stored in 
'=  Active Directory.  This is useful when you don't know exactly where an 
'=  object is located or want to move something.
'=  
'=  Usage: Wscript.Echo distinguish("DevinH","user") 
'=  Returns: cn=DevinH,ou=MyUsers,dc=ScriptCentric,dc=com       
'======================================================

Function distinguish(strObject, strType)
    Select case strType
        Case lcase("computer")
            strobject = strObject & "$"
        Case lcase("user")
            'Good
        Case lcase("group")
            'Good
        Case else
            Wscript.Echo "Their is an error in the script"
    End Select
    ' Determine DNS domain name (this could be hard coded).
    Set objRootDSE = getObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.get("defaultNamingContext")
    
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = createObject("ADODB.Connection")
    Set objCommand = createObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    
    Set objCOmmand.ActiveConnection = objConnection
    objCommand.CommandText = _
    "Select distinguishedname, Name, Location from 'LDAP://" & strDNSDomain & _
    "' Where objectClass='" & strType & "' and samaccountname='" & strobject & "'"
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    Set objRecordSet = objCommand.execute
    objRecordSet.MoveFirst
    
    Do Until objRecordSet.EOF
       distinguish = objRecordSet.Fields("distinguishedname")
       objRecordSet.MoveNext
    Loop
End Function

'***************end of code*************