Defaults - Accessing Nested Value

Hi,

I know how to append a value to an array using the defaults command, however, I’m not entirely sure how to access an array (or any key/value, for that matter) that’s nested inside another key.

So, my question is: How do I change the value of a key in a dictionary that’s nested inside another dictionary? For example, in com.apple.loginitems:

[code]<?xml version="1.0" encoding="UTF-8"?>

SessionItems Controller CustomListItems CustomListItems [/code] I want to append to the array under the CustomListItems key, but I'm unsure how to access that array. All the examples I could find assume you're writing to the primary dictionary only.

If you haven’t guessed, I’m using this to add login items to various users. I know you can use AppleScript to do this for the person you are logged in as, but this will be done to several accounts across a lab remotely.

Thanks,
-Rob

Hi Rob,

you can do that for every account on the machine,
the only requirements are: Apple Remote Events must be enabled and the target account(s) must be logged in.
Here an example script, it adds iTunes to the login items of user “test”


property user_name : ""
property pass_word : ""
property theUser : "test"
property theApp : "iTunes.app"

tell (system info) to set HostName to host name
set pathApp to POSIX path of (path to application theApp)
set TheID to last word of (do shell script "dscl . -read /Users/" & theUser & " UniqueID")

if pass_word is "" then
	set eppc to "eppc://" & HostName & "/?uid="
else
	set eppc to "eppc://" & user_name & ":" & pass_word & "@" & HostName & "/?uid="
end if

try
	using terms from application "Finder"
		tell application "Finder" of machine (eppc & TheID)
			get processes -- a trick to launch System Events on the remote user
		end tell
	end using terms from
	
	using terms from application "System Events"
		tell application "System Events" of machine (eppc & TheID)
			make new login item at end of login items with properties {path:pathApp, hidden:false}
		end tell
	end using terms from
on error
	display dialog "User \"" & theUser & "\" with ID " & TheID & " is not logged in"
end try

I will give that a try, since I’m failing at defaults. It keeps giving me a parse error whenever I try to write to the login items plist.

[edit]

Although, if I’m already logged in as that user, why not simply this?:

set appPath to POSIX path of alias "path:to:app"
tell application "System Events"
   make login item at end with properties {path:appPath, hidden:false}
end tell

Since I’m going about this via ARD, I can just osascript that bit. I was trying to avoid having to log all the computers out, log them back in, and set the login items. My scripts all worked fine for Tiger and earlier, I’m just having some problems with the change in Leopard.

I’m doing the following via ARD, but defaults is spitting out that it’s having trouble parsing it and that I should single-quote it.:

do shell script "sudo defaults write /Users/foo/Library/Preferences/com.apple.loginitems '{<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
	<key>SessionItems</key>
	<dict>
		<key>Controller</key>
		<string>CustomListItems</string>
		<key>CustomListItems</key>
		<array>
			<dict>
				<key>CustomItemProperties</key>
				<dict>
					<key>com.apple.loginitem.legacyprefs</key>
					<dict>
						<key>Hide</key>
						<false/>
						<key>Path</key>
						<string>/Library/Scripts/Login Scripts/myApp.app</string>
					</dict>
				</dict>
				<key>Name</key>
				<string>myApp</string>
			</dict>
		</array>
	</dict>
</dict>
</plist>}'"

I tried it various ways, such as removing the tabs and newlines, but I get teh same result. It’s not the whitespace that’s causin the parse to fail, and this is copied straight from the com.apple.loginitems.plist of the test account.

Thanks,
-Rob

sorry, you’re obviously using Tiger, so you have to change this line


.
set TheID to last word of (do shell script "/usr/bin/nireport / /users name uid | grep " & theUser)
.

Of course, but I thought, you want to do this not only for the current logged in account

No, it’s for Leopard. Let me explain my situation:

I have a lab of ~60 computers running 10.5. I’m updating my old account creation scripts for leopard. Pretty much everything is the same (same DSCL commands, same format for accounts, etc.) for Leopard as it was for Tiger. The only thing that’s changed are the parental controls (just replace the Tiger format with the new Leopard format), and the login items, which are now contained in their own preference file instead of the loginwindow prefs.

My script basically reads a big list of “users” (course names, actually) from a CSV file. Based on this list, it then runs through the series of dscl commands to create the accounts. It’s breaking at the login items portion, where I’m trying to set the login items for each of the courses (which is just a compiled script to mount their public sharepoint). I had hoped to simply append the login item to the appropriate array, but it’s nested too deeply for defaults to access it (this utility needs updating…). So, my other option was either to feed defaults a complete loginitems plist, or to go about it some other way.

I’m trying to avoid logging out/logging back in, etc. I’d like to do everything in one swift boot like the previous script.

I haven’t tested it yet, but in Leopard you have improved capabilities to edit (write) property list files in System Events.
On other suggestion is to use a default login item pref file and duplicate it to the destination location.
But you can also create dicts and arrays with defaults.

unfortunately suggestion #1 and #3 is like a puzzle game :wink:

Oh? Hmm. I’ll poke around on the forums for any AS solutions to writing to a plist directly since defaults isn’t being nice to me today.

[edit]

If you know of any posts with some examples of editing plist with only AS and no defaults, let me know. Not having great results in the forum search.

Thanks,
-Rob

facepalms Okay, I fixed it. I just realized I was using the defaults write to plug in XML data instead of whatever format it’s called that defaults uses. No wonder it’s not parsing.

Thanks for all the suggestions/help.

In Leopard you have more control over xml (plist files) using system events.

Looking at thispage from Apple I had a little learning curve to get this to work.

tell application "System Events"
	
	set this_plistfile to property list file "~/Desktop/test.plist"
	set array to "CustomListItems"
	set dictionary to "SessionItems"
	make new property list item at end of property list item array of property list item dictionary of this_plistfile with properties {kind:number, value:1}
	make new property list item at end of property list item array of property list item dictionary of this_plistfile with properties {kind:string, value:"a string"}
	make new property list item at end of property list item array of property list item dictionary of this_plistfile with properties {kind:list, name:"la_list"}
end tell

** the only thing that does not show is the name, still working on it?